機械学習のお勉強(活性化関数と損失関数と過学習対策)
活性化関数
活性化関数は、入力信号の総和がどのように活性化するかを決定する役割を持つ
単位ステップ関数 👈パーセプトロン
def step_function(x): if x > 0: return 1 else: return 0
or
def step_function(x): if x > 0: return 1 elif x == 0: return 0.5 else: return 0
符号関数 👈パーセプトロン
def step_function(x): if x > 0: return 1 elif x == 0: return 0 else: return -1
線形関数 👈ADALINE,線形回帰
def linear_function(x): return x
区間線形関数 👈サポートベクトルマシン
def piecewise_linear_function(x): if x >= 1/2: return 1 elif -1/2 < x < 1/2: return x + 1/2 else: return 0
シグモイド関数 👈ロジスティック回帰、ニューラルネットワーク
def sigmoid(x): return 1 / (1 + np.exp(-x))
双曲線正接 👈ニューラルネットワーク
def sigmoid(x): return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))
ReLU関数 👈ニューラルネットワーク
出力値の飽和を防ぐことで勾配消失問題を克服した手法
def relu(x): return np.maximum(0,x)
ReLU関数 👈ニューラルネットワーク
出力値の飽和を防ぐことで勾配消失問題を克服した手法
def relu(x): return np.maximum(0,x)
Leaky ReLU関数 👈ニューラルネットワーク
負の入力で微分が0になる問題を対処する
alpha = 0.01 def relu(x): if x > 0: return x else: return alpha * x
aplhaは微小量にすることが一般的
Parametric ReLU関数 👈ニューラルネットワーク
上記のalphaが学習によって更新されるしくみを採用。
また、入力の次元によってalphaが異なる値をとれるようにしている。
Expotential Linear Unit 👈ニューラルネットワーク
正規化のように働き学習が早く進む他、ノイズに対して頑強だと言われている
alpha = 1 def ELU(x): if x > 0: return x else: return alpha * (np.exp(x) - 1)
ソフトマックス関数 👈分類問題に使用
def softmax(x): exp_a = np.exp(x) sum_exp_a = np.sum(exp_a) y = exp_a / sum_exp_a return y
- ソフトマックスの出力の総和は1になるという性質があり、この性質により出力を確率と解釈することができる。
- 学習と推論のうち、学習の際にこの関数が関係してくる。
まとめ
重要なことは非線形の関数であるということ。 線形関数では層を深くしても隠れ層のないネットワークになり、多層にする意味がなくなってしまう。
損失関数
二乗和誤差 👈回帰問題に使用
def mean_squared_error(y,t): return 0.5 * np.sum((y-t)**2)
交差エントロピー誤差 👈カテゴリ識別問題に使用
def cross_entropy_error(y, t): delta = 1e-7←発散防止 return -np.sum(t * np.log(y+delta))
y:softmax t:one-hot-encoding と考えると、正解ラベルである確率が1であるときに最小値になる
過学習対策
DropOut
イテレーションごとにネットワークからランダムに選ばれたユニットを隠し、学習を行う
バッチ正規化
バッチごとに平均beta、分散gammaに変換になるよう入力を調整する
多層ニューラルネットでBatch Normalizationの検証 - Qiita
Weight decay
L2正規化
損失関数に重みをいれることで、パラメータが極端な値になることを防ぐ
L_w = L + rambda * 1 / 2 * sum(x[k] ** 2 for k in range(i))
L1正規化
L_w = L + rambda * sum(abs(x[k]) for k in range(i))
Gradient Clipping
勾配爆発を防ぐことで学習を安定化
考え方は損失関数の勾配をある範囲を超えないようclippingすること
機械学習のお勉強(性能評価)
全体の考え方
機械学習における学習方法と性能評価の基礎知識 - Build Insider
交差検定(クロスバリデーション)など機械学習の評価方法まとめ : 新規事業のつくり方
検証
ホールドアウト法
学習データとテストデータを単純に分割
参考:
機械学習の性能を正しく評価するための検証手法 - Qiita
k分割交差検証
ランダムにk個に分割し、k-1個をテストに使用し、これをk回繰り返す
参考:
「そのモデルの精度、高過ぎませんか?」過学習・汎化性能・交差検証のはなし - 六本木で働くデータサイエンティストのブログ
http://musashi.osdn.jp/tutorial/mining/xtclassify/accuracy.html
入れ子式の交差検証
さまざまな機械学習のアルゴリズムからどれかを選択したい時に使用
クロスバリデーションでは予測性能を評価できない!ダブルクロスバリデーション(クロスモデルバリデーション)のススメ : 大学教授のブログ (データ分析相談所)
性能評価
正解率以外にも評価する指標が存在する
混同行列
真陽陰性(TP,TN)、偽陽陰性(FP,FN)を表現する行列
sklearn -> confusion_matrix(y_true=
で作成できる
適合率
PRE = TP / (TP + FP)
再現率
REC = TP / (FN + TP)
F1
よく使用される評価指標らしい
F1 = 2 * (PRE * REC) / (PRE + REC)
画像の読み込み方法
- chainer
- OpenCV
- listdirで読み込み
画像読み込みサンプル(OpenCV)
フォルダ分けされた大量の学習画像を一括で読みこむ方法(python) - 技術メモ集
# -*- coding: utf-8 -*- import os import cv2 class Prepro(object): def __init__(self): self.data_dir_path = u"./data/" self.dir = os.listdir(r'./data/') def get_image_and_label(self): dir_list = sorted([x for x in self.dir if os.path.isdir(self.data_dir_path+x)]) label_f = open('list.txt', 'w') image_list = [] label_list = [] dir_label = 0 for dir_name in dir_list: label_f.write(str(dir_name)+","+str(dir_label)+"\n") file_list = os.listdir(self.data_dir_path+dir_name) for file_name in file_list: root, ext = os.path.splitext(file_name) if ext == u'.png' or u'.jpeg' or u'.jpg': abs_name = self.data_dir_path+dir_name+"/"+file_name image = cv2.imread(abs_name) image_list.append(image) label_list.append(dir_label) dir_label +=1 return image_list, label_list if __name__ == '__main__': prepro = Prepro() images, lists = prepro.get_image_and_label()
参考:
face_prediction/facePredictionTraining.py at master · tommyfms2/face_prediction · GitHub ここのwhoiswhoあたり
フォルダ内の全画像ファイルに対して一括処理を行う(python) - 技術メモ集
[Python]フォルダ内のファイルを取得する方法 - Qiita
python:画像処理tips その4 フォルダ内の画像の大きさを揃える - MATHGRAM
cnn-animeface-keras/animeface.py at master · satopirka/cnn-animeface-keras · GitHub
パラメータチューニング
sk-learn: ベイズ的最適化、グリッドサーチ、ランダムサーチも可能
ベイズ的最適化・実験計画法のお勉強
目的
少ない実験回数で最適なパラメータを導出したい
ベイズ的最適化
まずはこの2つを見てお勉強
要点を箇条書きでまとめる
どういう実験を行えばblack box関数を最適化できるか
一回の実験コストが高い場合に有用
black box関数をgausiann processでモデル化
ベイズではblack box関数の最適化を行う代わりに獲得関数を最適化(活用・探索)
活用とは:近しい分野の本を読む
探索:本屋に行って面白い本を探す
活用と探索のトレードオフが重要
[TODO] 強化学習 活用 探索 でググッてこのあたりの知識を強化
参考: 1020:ベイズ的最適化の入門と応用 機械学習による機械学習の実験計画 - YouTube
» 機械学習のハイパーパラメータ探索 : ベイズ最適化の活用 TECHSCORE BLOG ←最高にわかりやすい!コード付き!!
第3回 機械学習のためのベイズ最適化入門|Tech Book Zone Manatee ←わかりやすい!
PRML第6章 ガウス過程による回帰 Python実装 - Qiita ←わかりやすい!
統計学の考え方を抑えて機械学習との関連と相違を整理 - HELLO CYBERNETICS
ライブラリ
sk-learn: ベイズ的最適化、グリッドサーチ、ランダムサーチも可能
Pythonでベイズ最適化を使ってハイパーパラメータを探索するライブラリ実装のメモ - Qiita
ハイパーパラメータの最適化と結果の見方【Pythonとscikit-learnで機械学習:第8回】
GpyOpt:
Pythonでベイズ最適化を行うパッケージ GPyOpt - Qiita
カーネル
カーネルとはふたつのベクトル xx と yy の内積を(たいていはとても高次元の)特徴空間で計算する方法
参考: カーネルとは直感的に説明するとなんなのか? - Qiita
交差検定
例:正解付きのデータをK分割して,そのうち1つをテストデータに,残りのK-1個を訓練データとして学習と精度の評価を行う
参考:
第21回(最終回) 機械学習 はじめよう:機械学習 はじめよう|gihyo.jp … 技術評論社
実験計画法
(TBD)
参考:
Excelで学ぶ実験計画法の基礎(3):試作品の数を劇的に減らす直交配列実験の実務 (1/5) - MONOist(モノイスト)
kinect v2をROS(KINETIC)で動かしてみる
環境設定
手順:Ubuntu16.04: Kinect V2の設定 | demura.net
GitHub - OpenKinect/libfreenect2: Open source drivers for the Kinect for Windows v2 device
GitHub - code-iai/iai_kinect2: Tools for using the Kinect One (Kinect v2) in ROS
修正点
–from-paths ros -> - -from-paths
Unable to compile anymore · Issue #377 · code-iai/iai_kinect2 · GitHub
iai_kinect2 -> kinect_registrationパッケージのCMakeLists.txtに
add_definitions( -fexceptions )
を追加
実行結果
depth
PCL
PCL(Point Cloud Library)+ROSで3次元画像処理入門 - karaage. [からあげ]
mzrandom : kinect から 距離画像を取ってくるROSパッケージ
www.slideshare.net
Python x PointCloud
http://olinivlab.weebly.com/uploads/2/2/1/5/22158624/ros_by_example_hydro_volume_1.pdf
Zの取得
#!/usr/bin/env python import roslib import rospy from sensor_msgs.msg import PointCloud2 import numpy import pylab import time import sensor_msgs.point_cloud2 as pc2 def callback(data): resolution = (data.height, data.width) # 3D position for each pixel img = numpy.fromstring(data.data, numpy.float32) cloud_points = [] for p in pc2.read_points(data, field_names = ("x", "y", "z"), skip_nans=False): cloud_points.append(p[2]) z_points = numpy.array(cloud_points, dtype=numpy.float32) z = z_points.reshape(resolution) print z[data.height/2 , data.width/2] def listener(): rospy.init_node('listener', anonymous=True) rospy.Subscriber('/kinect2/sd/points', PointCloud2, callback) rospy.spin() if __name__ == "__main__": listener()
rvizでの表示、TFの出し方
roslaunch kinect2_bridge kinect2_bridge.launch publish_tf:=true
FixedFrame -> kinect2_link へ変更
roslaunch kinect2_bridge kinect2_bridge.launch publish_tf:=true fps_limit:=10
TFについて
SD, HD, QHD
画質の違い【SD/HD/フルHD/4K】 - 動画配信サービスナビ
参考
How to install libopenni2-dev on Ubuntu 16.04 (Xenial Xerus)
Gazebo+ROSのお勉強
Gazebo Tutorial
わかりやすいブログ
Controller と HardwareInterface との間の処理の仕組み(1. ロボットモデルの定義と登録) - Qiita
Controller と HardwareInterface との間の処理の仕組み(2. RobotHWSimのプラグインについて) - Qiita
Controller と HardwareInterface との間の処理の仕組み(3. Controllerについて) - Qiita
Gazebo から ROS のプラグインを呼ぶ処理の仕組み(1. Gazebo起動時のSystemPluginの読込み) - Qiita
ros_controls/ros_controllers の制御の仕組み (position/effort/velocity_controllers の基礎) - Qiita
参考
Gazeboによるマニピュレータのシミュレーション - 研究紹介ページ
Gazebo + ROS で自分だけのロボットをつくる 5. GazeboとROSの連携 - Qiita
gazebo、ros_controlについて - akak1のブログ
No.6-1:GazeboをROSに繋ぐ (ROSの概要 編) - 九州工業大学 CIR-KIT Blog
No.6-2:GazeboをROSに繋ぐ (どのGazebo/ROSのバージョンの組み合わせを使うか 編) - 九州工業大学 CIR-KIT Blog
No.6-3:GazeboをROSに繋ぐ (Gazebo_ros_pkgsをインストールする 編) - 九州工業大学 CIR-KIT Blog
No.6-4:GazeboをROSに繋ぐ (Roslaunchを使う 編) - 九州工業大学 CIR-KIT Blog
No.6-5:GazeboをROSに繋ぐ (GazeboにおけるURDF 編) - 九州工業大学 CIR-KIT Blog
No.6-6:GazeboをROSに繋ぐ (ROSにおけるGazeboのプラグイン 編) - 九州工業大学 CIR-KIT Blog
No.6-7:GazeboをROSに繋ぐ (ROS Control 編) - 九州工業大学 CIR-KIT Blog
No.6-8:GazeboをROSに繋ぐ (ROS Communication 編) - 九州工業大学 CIR-KIT Blog
No.6-9:GazeboをROSに繋ぐ (ROS Plugin 編) - 九州工業大学 CIR-KIT Blog
機械学習のお勉強(単層ニューラルネットワーク)
人工ニューロン
神経細胞を2値処理を行う単純なゲートとして表現。
z = w0 * x0 + w1 * x1 + .... + wm * xm and phi(z)={ 1 (z>=0) or -1 (z<0)
これは脳内の一つのニューロンの働き(発火するかしないか)を模倣している。
パーセプトロンの学習規則
- 重みを0 or 値の小さい乱数で初期化する
- トレーニングサンプルxjごとに以下の手順で実行
- 出力値を計算(上記で言う1 or -1)
- 重みの更新
重みの更新方法
- wj = wj * delta wj <- delta wj = myu * (y - y^) * xj
- delta w0 = myu (y - y^)
- delta w1 = myu (y - y^) * x1
- delta w2 = myu (y - y^) * x2
このように重みすべてが更新されるまでy^は再計算されない。
パーセプトロンの収束性
- 2つのクラスが線形分離可能な場合
- 学習率が小さい場合
に限られる
ADALINEと学習の収束(Adaptive Linear Neuron)
重みの更新方法がパーセプトロンと異なる
単位ステップ関数ではなく、線形活性化関数に基づいて重みが更新される
目的関数
クラスラベルと計算結果の誤差平方和
J(w) = 1/2 sum(y - phi(z))2
z = w * x
特徴
線形活性化関数により、微分可能
凸関数出るため勾配降下法を用いて目的関数を最小化する重みをみつけることができる
重みの更新(バッチ勾配降下法)
w = w + delta w delta w = - myu * sum ( y - phi(z) ) * x z = w * x
重みの更新はトレーニングデータセットすべてのサンプルに基づいて計算する(バッチ勾配降下法)
パフォーマンスを上げるポイント
特徴量のスケーリング!
X_std = (X - X.mean()) / X.std()
平均を引き、標準偏差で割る。平均0 , 標準偏差を1にする。
確率的勾配降下法
w = w + delta w delta w = - myu * ( y - phi(z) ) * x z = w * x
sumがない分高速に収束させることができる。その分1サンプルの影響を受けるためノイズが多い
また、データが追加されれば随時学習するオンライン学習が可能
ポイント
エポックごとにトレーニングデータをシャッフルして循環を避ける
適応的学習率を使う(ex: myu = a / (iter回数 + b))
ミニバッチ学習
確率的・バッチ勾配降下法の折衷案
すべてをバッチとするわけでなくいくつかを抽出し、ミニバッチとして学習する
ロジスティック回帰(クラス確率のモデリング)
名前とは裏腹に回帰ではなく分類のためのモデル
線形分離可能なクラスに関してのみ有効
logit(p) = log p / (1 - p) logit(p(y = 1 | x)) = w * x = z p = phi(z) = 1 / (1 + e^-z)
p : シグモイド関数
サンプルがクラスに属している確率が予測できる(天気予報や医療診断などに用いられる)
尤度関数
0,1の2クラス分類より以下のように表せる
L(w) = PI (phi(z))^y (1- phi(z))^(1-y)
コスト関数
J(w) = sum (-y * log(phi(z)) - (1 - y)* log(1 - phi(z)))
実装
ADALINEのコスト関数を上記に置き換えるだけ
過学習・学習不足
データに対してモデルが複雑・簡単すぎるときに発生する
過学習をするモデル(偶発誤差):「バリアンス(分散?)が高い」という
学習不足をするモデル(系統誤差):「バイアス(平均?)が高い」という
モデルの汎化誤差 = バイアス2 + バリアンス + ノイズ
バイアスとバリアンスの調整手法(L2正規化)
lambda * || w || ^2 / 2 = lambda * sum(w^2) / 2
TODO:バリアンスとバイアスのトレードオフについて調査