- 投稿日:2020-03-30T22:38:15+09:00
ニューラルネットでの簡単な分類モデル
前回に引続き、ニューラルネットについての勉強をしてみました。
今回は、簡単な分類モデルの構築に挑戦。
以下の2つの変数を準備します。0 \le x_1,x_2 \le 1そして、2つの和によって、以下のような分類をしてみる。
t(x_1,x_2) = \left\{ \begin{matrix} 0 & (x_1 + x_2 < 1) \\ 1 & (x_1 + x_2 \ge 1) \end{matrix} \right.こんなシンプルなモデルを実装してみます。
0層??のニューラル考え方としては、以下の数式を検討します。y(x_1,x_2) = \sigma(w_1 x_1 + w_2 x_2 + w_0)ただし、σはシグモイド関数で、そのアウトプットは[0,1]に限定されます。これが本当特徴的で、y<0.5なら分類A、y>0.5なら分類B、のような意味を持たせているようです。実はこれって結構肝の部分な気がします。ニューラルネットでは、w1,w2,w0を調整することで、答えを出すような仕組み。ということで、誤差を見積もるファンクションを検討すると、この場合は交差エントロピーになるようです。具体的には、x1,x2に対して正解tを与えたとき、その交差エントロピーは以下のように表現されます。
E(w_1,w_2,w_0) = - (t \ln y + (1-t) \ln (1-y) )詳細は、「パターン認識と機械学習」などを参照していただく(p.235あたり)として、ざっくりとしたイメージとしては・・・。0<y<1に注意して
- yをクラスAの確率と見なす(t=1のとき)
- 1-yをクラスBの確率と見なす(t=0のとき)
すると、tが与えられたときの確率p(t)は、X^0=1を利用して式を1本化することで
p(t)= y^t (1-y)^{1-t}となるようです。あとはログをとれば、E(w1,w2,w0)の式が導出されます。これを各サンプルごとに掛け算するので、各yiに対して
p(t)= \prod_i y_i^t (1-y_i)^{1-t}となるので、ログをとって
\ln p(t)= \sum_i (t \ln y_i + (1-t) \ln (1-y_i) )となります。これは正解率の和のような感じなので、合っているほど値が大きくなります。そこで、最適化(最小化)問題として解くために符号を反転させてEを定義しました。繰り返しますが、以下の交差エントロピーになります。(複数サンプルバージョン)
E(w_1,w_2,w_0) = - \sum_i (t \ln y_i + (1-t) \ln (1-y_i) )では、実際にソースコードを書いてみます。
まずは、変数部分。# make placeholder x_ph = tf.placeholder(tf.float32, [None, 3]) t_ph = tf.placeholder(tf.float32, [None, 1])x_phは入力部分、本当は2つのはずですが、w0用のダミー変数(1固定)を入れておきました。これはいらないかも?
t_phは出力部分で、正解を与えるためのものです。0か1が入ります。そして、これに入れるサンプルデータは適当に乱数で設定します。
# deta making??? N = 1000 x = np.random.rand(N,2) # sum > 1.0 -> 1 : else -> 0 t = np.floor(np.sum(x,axis=1)) # ext x x = np.hstack([x,np.ones(N).reshape(N,1)])xを2つ作ったのち、yを作って、その後、ダミー変数を1個追加してます。これによって、xは1サンプルで3次元となっています。yはx1+x2が1以上のときに1、1未満では0となるように、小数点切捨てを利用して作成しています。
そして、ニューラルネットワークの層はとりあえず2つほど準備。
# create newral parameter(depth=2,input:3 > middle:30 > output:1) hidden1 = tf.layers.dense(x_ph, 30, activation=tf.nn.relu) newral_out = tf.layers.dense(hidden1, 1, activation=tf.nn.sigmoid)あとは、交差エントロピーを定義して、最小化するように学習を定義します。単なるコピペですね。収束アルゴリズム設定など、まだよくわかっていません。
# Minimize the cross entropy ce = -tf.reduce_sum(t_ph * tf.log(newral_out) + (1-t_ph)*tf.log(1-newral_out) ) optimizer = tf.train.AdamOptimizer() train = optimizer.minimize(ce)というわけで、上記を適当に組み合わせて、全体のソースを作ってみました。
import numpy as np import tensorflow as tf # deta making??? N = 1000 x = np.random.rand(N,2) # sum > 1.0 > 1 : else > 0 t = np.floor(np.sum(x,axis=1)) # ext x x = np.hstack([x,np.ones(N).reshape(N,1)]) train_x = x train_t = t # make placeholder x_ph = tf.placeholder(tf.float32, [None, 3]) t_ph = tf.placeholder(tf.float32, [None, 1]) # create newral parameter(depth=2,input:3 > middle:30 > output:1) hidden1 = tf.layers.dense(x_ph, 30, activation=tf.nn.relu) newral_out = tf.layers.dense(hidden1, 1, activation=tf.nn.sigmoid) # Minimize the cross entropy ce = -tf.reduce_sum(t_ph * tf.log(newral_out) + (1-t_ph)*tf.log(1-newral_out) ) optimizer = tf.train.AdamOptimizer() train = optimizer.minimize(ce) # initialize tensorflow session sess = tf.Session() sess.run(tf.global_variables_initializer()) for k in range(1001): if np.mod(k,100) == 0: # get Newral predict data y_newral = sess.run( newral_out ,feed_dict = { x_ph: x, # xに入力データを入れている }) ce_newral = sess.run( ce ,feed_dict = { x_ph: x, # xに入力データを入れている t_ph: t.reshape(len(t),1) # yに正解データを入れている }) sign_newral = np.sign(np.array(y_newral).reshape([len(t),1]) - 0.5) sign_orig = np.sign(np.array(t.reshape([len(t),1])) - 0.5) NGCNT = np.sum(np.abs(sign_newral-sign_orig))/2 # check predict NewralParam print('[%d] loss %.2f hit_per:%.2f' % (k,ce_newral,(N-NGCNT)/N)) # shuffle train_x and train_t n = np.random.permutation(len(train_x)) train_x = train_x[n] train_t = train_t[n].reshape([len(train_t), 1]) # execute train process sess.run(train,feed_dict = { x_ph: train_x, # x is input data t_ph: train_t # t is true data }) # test用 x = np.array([0.41,0.5,1]).reshape([1,3]) loss_newral = sess.run( newral_out ,feed_dict = { x_ph: x, # xに入力データを入れている }) # <0.5なら成功かな print(loss_newral)これを動かすと以下のようになります。
[0] loss 727.36 hit_per:0.35 [100] loss 587.68 hit_per:0.78 [200] loss 465.78 hit_per:0.89 [300] loss 358.70 hit_per:0.93 [400] loss 282.45 hit_per:0.94 [500] loss 230.54 hit_per:0.96 [600] loss 194.34 hit_per:0.97 [700] loss 168.11 hit_per:0.98 [800] loss 148.34 hit_per:0.98 [900] loss 132.93 hit_per:0.99 [1000] loss 120.56 hit_per:0.99 [[0.27204064]]lossと書かれたところは、交差エントロピーの値、徐々に減っている様子が分かります。(変数名変えろよ・・・と突っ込み)
そして、hit_perは、学習データに対しての正解率。1.00で100%となりますが、99%の成功率のようです。
最後に、適当なテスト、x1=0.45,x2=0.5を入れたときのニューラルネットのアウトプットを出しています。この場合は、クラスBのt=0のはずなので、アウトプットは0.5より小さければ正解、かつ、0.5に近いほど迷っていると読み取れます。今回は0.27なので結構自信を持って答えてOKそうです。最後に正解の出し方について、ちょっとだけ書いておきます。ポイントはNGの数を出しているところだと思います。以下一部ピックアップ。
# get Newral predict data y_newral = sess.run( newral_out ,feed_dict = { x_ph: x, # xに入力データを入れている }) sign_newral = np.sign(np.array(y_newral).reshape([len(t),1]) - 0.5) sign_orig = np.sign(np.array(t.reshape([len(t),1])) - 0.5) NGCNT = np.sum(np.abs(sign_newral-sign_orig))/2y_newralには、xから推定した分類情報が[0,1]の範囲で入っています。この数値は、0.5より大きいか小さいかで、どちらの分類に入るか、という意味なので、それを判別できる形に変換する必要があります。そこで、0.5という数値を引いて、[-0.5,0.5]の範囲に平行移動してから、符号だけ取り出して、+1か-1のどちらかが選択されるようにしました。同様の処理を、t(正解)に対しても実施して、+1/-1の正解値を生成。
この二つは同じ値のときに正解、違う値のときには不正解なのですが、パターンを書き出すと、以下のような関係にあります。
推定値 正解値 推定の正しさ 推定値-正解値 1 1 OK 0 1 -1 NG 2 -1 1 NG -2 -1 -1 OK 0 そこで、sum(abs(推定値-正解値))/2を計算することによって、NGの数が数えられます。これを利用することで、正解率???HIT率が計算できました。
めでたく動いたわけですが、ニューラルネットの設定をもっとシンプルに、中間層なしでやると、収束に時間がかかったり、やりすぎて途中でゼロ割???っぽいことが起きるようでした。
例えば以下のような設定で行くと・・・newral_out = tf.layers.dense(x_ph, 1, activation=tf.nn.sigmoid)結果は???
[0] loss 761.80 hit_per:0.50 [100] loss 732.66 hit_per:0.50 [200] loss 706.48 hit_per:0.50 [300] loss 682.59 hit_per:0.50 [400] loss 660.61 hit_per:0.50 [500] loss 640.24 hit_per:0.54 [600] loss 621.26 hit_per:0.62 [700] loss 603.52 hit_per:0.70 [800] loss 586.88 hit_per:0.76 [900] loss 571.22 hit_per:0.80 [1000] loss 556.44 hit_per:0.84 [[0.52383685]]となって、なんだかいまひとつようです。何がどう利いているのか???私もまだまだ理解不足ですが、ある程度中間層があることで、何かが起きて、上手くいっているようです。
どこまで増やせばどんな状態になるのか?その辺りの理論も追々勉強していきたいと思います。
- 投稿日:2020-03-30T12:39:19+09:00
jetson-nano のセットアップ
nv-jetson-nano-sd-card-image-r32.3.1.zip を使った場合の話。
TensorFlow
https://docs.nvidia.com/deeplearning/frameworks/install-tf-jetson-platform/index.html
に従ってsudo apt-get update sudo apt-get -y install libhdf5-serial-dev hdf5-tools libhdf5-dev zlib1g-dev zip libjpeg8-dev liblapack-dev libblas-dev gfortran python3-pip libatlas-base-dev sudo pip3 install -U pip testresources setuptools cython sudo pip3 install -U numpy==1.16.1 future==0.17.1 mock==3.0.5 h5py==2.9.0 keras_preprocessing==1.0.5 keras_applications==1.0.8 gast==0.2.2 futures protobuf pybind11 sudo pip3 install --pre --extra-index-url https://developer.download.nvidia.com/compute/redist/jp/v43 tensorflowでTensorFlowは入った
keras
sudo pip3 install kerashttps://github.com/keras-team/keras/blob/master/examples/mnist_mlp.py
OpenCV
import cv2 cv2.__version__4.1.1が入ってた
cudaのサンプル
cp -r /usr/local/cuda-**/sample ~/ cd ~/sample make -j4参考