質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Q&A

解決済

1回答

33941閲覧

機械学習の精度が上がらない

gittib_gittib

総合スコア102

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

0グッド

5クリップ

投稿2017/06/20 05:24

編集2017/06/28 06:29

###前提・実現したいこと
tensorflowを使ったテストプログラムを作成し、機械学習に必要十分なデータ量がどれだけなのか、その感覚を掴みたい、またはそのデータ量を推定するための見当のつけ方を身につけたい。です。

###発生している問題・エラーメッセージ
現在、「4つの値を入力とし、そのうち2番目の値と4番目の値が一致していれば0、不一致なら1を出力する」というルールで入力データ・学習データを自動生成し、学習・評価するプログラムを回しています。
**これの精度が上がらず、なぜ上がらないのかご教授いただきたい。**というのが今回の質問になります。

以下は100個のデータを渡して10000回学習を行い、1000回ごと及び学習終了後にテストデータによる評価をした結果です。誤差の値も上下を繰り返しており、精度も90%にすら届きません。

loss: 0.694365 accuracy: 0.400000 loss: 0.691950 accuracy: 0.600000 loss: 0.700912 accuracy: 0.400000 loss: 0.695201 accuracy: 0.400000 loss: 0.691830 accuracy: 0.600000 loss: 0.703954 accuracy: 0.400000 loss: 0.691710 accuracy: 0.600000 loss: 0.686128 accuracy: 0.600000 loss: 0.694570 accuracy: 0.400000 loss: 0.695068 accuracy: 0.400000 loss: 0.690764 accuracy: 0.600000

###該当のソースコード
ソースコード自体にスクリプトのパスは書かず、コマンドラインからpythonコマンドを叩いています。

Python

1import numpy as np 2from numpy.random import randint 3import tensorflow as tf 4from pprint import pprint 5 6# パラメータ設定 7BATCH_SIZE = 100 # 1回の学習に用いるデータ数 8NUM_TESTS = 25 # テストデータのデータ数 9INPUT_DIMENSION = 4 # 入力データの次元数 10HIDDEN_DIMENSION = 2 # 隠れ層の次元数 11OUTPUT_CLASSES = 2 # 2クラスロジスティック回帰 12LEARNING_RATE = 0.2 # 学習率 13TRAIN_TIMES = 10000 # 学習回数 14 15# テストデータの生成 16# [1]と[3]の値は1か2のみで、この二つを比較し出力とする 17def createSuperviserData(nDatas): 18 inData = [] 19 outData = [] 20 for i in range(nDatas): 21 tmpIn = [ 22 float(randint(18, 81)), 23 float(randint(1, 3)), 24 float(randint(18, 81)), 25 float(randint(1, 3)), 26 ] 27 if tmpIn[1] == tmpIn[3]: 28 tmpOut = [1, 0] 29 else: 30 tmpOut = [0, 1] 31 inData.append(tmpIn) 32 outData.append(tmpOut) 33 return [inData, outData] 34 35# 推論モデル 36def inference(input_placeholder): 37 # 隠れ層を一つ設ける 38 with tf.name_scope('hidden'): 39 W = tf.Variable(tf.zeros([INPUT_DIMENSION, HIDDEN_DIMENSION]), name='weight') 40 b = tf.Variable(tf.zeros([HIDDEN_DIMENSION]), name='bias') 41 _h = tf.nn.relu(tf.matmul(input_placeholder, W) + b, name='inference') 42 43 W = tf.Variable(tf.zeros([HIDDEN_DIMENSION, OUTPUT_CLASSES]), name='weight') 44 b = tf.Variable(tf.zeros([OUTPUT_CLASSES]), name='bias') 45 y = tf.add(tf.matmul(_h, W), b, name='inference') 46 47 return y 48 49# 誤差。交差エントロピーを使う 50def loss(logits, labels): 51 labels = tf.to_int64(labels) 52 xentropy = tf.nn.softmax_cross_entropy_with_logits( 53 logits=logits, labels=labels) 54 xentropy_mean = tf.reduce_mean(xentropy, name='loss') 55 return xentropy_mean 56 57# 訓練モデル。勾配降下法 58def training(loss): 59 optimizer = tf.train.GradientDescentOptimizer(LEARNING_RATE) 60 train_step = optimizer.minimize(loss, name='training') 61 return train_step 62 63# モデルの精度確認 64def accuracy(logits, labels): 65 current_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(labels, 1)) 66 accuracy = tf.reduce_mean(tf.cast(current_prediction, tf.float32), name='accuracy') 67 return accuracy 68 69if __name__ == '__main__': 70 # プレースホルダーなどを定義 71 with tf.name_scope('superviser'): 72 inputs = tf.placeholder(tf.float32, shape=(None, INPUT_DIMENSION), name='x') 73 labels = tf.placeholder(tf.float32, shape=(None, OUTPUT_CLASSES), name='y') 74 test_input, test_output = createSuperviserData(NUM_TESTS) 75 test_feed_dict = {inputs: test_input, labels: test_output} 76 pprint({'test_input': test_input, 'test_output': test_output}) 77 78 # 演算用のモデルなどを定義 79 with tf.name_scope('main_op'): 80 logits = inference(inputs) 81 loss = loss(logits, labels) 82 train_op = training(loss) 83 accuracy = accuracy(logits, labels) 84 pprint({'inputs':inputs,'labels':labels,'logits':logits,'loss':loss, 85 'train_op':train_op,'accuracy':accuracy}) 86 print() 87 88 # 訓練開始 89 with tf.Session() as sess: 90 init = tf.global_variables_initializer() 91 init.run() 92 for i in range(TRAIN_TIMES): 93 x, y = createSuperviserData(BATCH_SIZE) 94 sess.run(train_op, feed_dict={inputs:x, labels:y}) 95 if i % (TRAIN_TIMES//10) == 0: 96 curLoss = sess.run(loss, feed_dict=test_feed_dict) 97 curAccuracy = sess.run(accuracy, feed_dict=test_feed_dict) 98 print('loss: %.6f accuracy: %.6f' % (curLoss, curAccuracy)) 99 print() 100 print('loss: %.6f' % sess.run(loss, feed_dict=test_feed_dict)) 101 print('accuracy: %.6f' % sess.run(accuracy, feed_dict=test_feed_dict)) 102

###試したこと
LEARNING_RATEとTRAIN_TIMESを中心に、パラメータを色々いじりながら試行を繰り返していますが、何が問題なのか見えていない状態です。

###補足情報(言語/FW/ツール等のバージョンなど)
Windows 10 にてVagrantでCentOS7の環境を用意し、そこでtensorflowのテストプログラムを作成しています。

[vagrant@localhost python]$ cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
[vagrant@localhost python]$ pyenv versions
system

  • anaconda3-4.0.0 (set by /home/vagrant/.pyenv/version)

[vagrant@localhost python]$ python -V
Python 3.5.3 :: Anaconda custom (64-bit)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

欠損関数が一向に下がらないのは、2クラス分類でソフトマックス関数を使っている為だと思われます。
2クラスではシグモイド関数を使うのが主流と聞いたので、
変更した所、欠損関数に限っては簡単に下げる事が出来ました。

python

1import numpy as np 2from numpy.random import randint 3import tensorflow as tf 4from pprint import pprint 5 6# パラメータ設定 7BATCH_SIZE = 100 # 1回の学習に用いるデータ数 8NUM_TESTS = 25 # テストデータのデータ数 9INPUT_DIMENSION = 4 # 入力データの次元数 10HIDDEN_DIMENSION = 2 # 隠れ層の次元数 11OUTPUT_CLASSES = 2 # 2クラスロジスティック回帰 12LEARNING_RATE = 0.2 # 学習率 13TRAIN_TIMES = 10000 # 学習回数 14 15# テストデータの生成 16# [1]と[3]の値は1か2のみで、この二つを比較し出力とする 17def createSuperviserData(nDatas): 18 inData = [] 19 outData = [] 20 for i in range(nDatas): 21 tmpIn = [ 22 float(randint(18, 81)), 23 float(randint(1, 3)), 24 float(randint(18, 81)), 25 float(randint(1, 3)), 26 ] 27 if tmpIn[1] == tmpIn[3]: 28 tmpOut = [1, 0] 29 else: 30 tmpOut = [0, 1] 31 inData.append(tmpIn) 32 outData.append(tmpOut) 33 return [inData, outData] 34 35# 推論モデル 36def inference(input_placeholder): 37 # 隠れ層を一つ設ける 38 with tf.name_scope('hidden'): 39 W = tf.Variable(tf.truncated_normal([INPUT_DIMENSION, HIDDEN_DIMENSION], 40 stddev=tf.sqrt(2.0 / INPUT_DIMENSION), 41 name='weight')) 42 b = tf.Variable(tf.truncated_normal([HIDDEN_DIMENSION], 43 stddev=0.1, 44 name='bias')) 45 46 _h = tf.nn.relu(tf.matmul(input_placeholder, W) + b, name='inference') 47 48 49 W = tf.Variable(tf.truncated_normal([HIDDEN_DIMENSION, OUTPUT_CLASSES], 50 stddev=tf.sqrt(2.0 / HIDDEN_DIMENSION), 51 name='weight')) 52 53 b = tf.Variable(tf.truncated_normal([OUTPUT_CLASSES], 54 stddev=0.1, 55 name='bias')) 56 y = tf.add(tf.matmul(_h, W), b, name='inference') 57 y = tf.nn.sigmoid(y) 58 59 return y 60 61# 誤差。交差エントロピーを使う 62def loss(logits, labels): 63 xentropy = -tf.reduce_sum(labels * tf.log(tf.clip_by_value(logits, 1e-10, 1.0), 64 ),axis=1) 65 xentropy_mean = tf.reduce_mean(xentropy, name='loss') 66 return xentropy_mean 67 68# 訓練モデル。勾配降下法 69def training(loss): 70 optimizer = tf.train.GradientDescentOptimizer(LEARNING_RATE) 71 train_step = optimizer.minimize(loss, name='training') 72 return train_step 73 74# モデルの精度確認 75def accuracy(logits, labels): 76 current_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(labels, 1)) 77 accuracy = tf.reduce_mean(tf.cast(current_prediction, tf.float32), name='accuracy') 78 return accuracy 79 80if __name__ == '__main__': 81 # プレースホルダーなどを定義 82 with tf.name_scope('superviser'): 83 inputs = tf.placeholder(tf.float32, shape=(None, INPUT_DIMENSION), name='x') 84 labels = tf.placeholder(tf.float32, shape=(None, OUTPUT_CLASSES), name='y') 85 test_input, test_output = createSuperviserData(NUM_TESTS) 86 test_feed_dict = {inputs: test_input, labels: test_output} 87 pprint({'test_input': test_input, 'test_output': test_output}) 88 89 # 演算用のモデルなどを定義 90 with tf.name_scope('main_op'): 91 logits = inference(inputs) 92 loss = loss(logits, labels) 93 train_op = training(loss) 94 accuracy = accuracy(logits, labels) 95 pprint({'inputs':inputs,'labels':labels,'logits':logits,'loss':loss, 96 'train_op':train_op,'accuracy':accuracy}) 97 print() 98 99 # 訓練開始 100 with tf.Session() as sess: 101 init = tf.global_variables_initializer() 102 init.run() 103 for i in range(TRAIN_TIMES): 104 x, y = createSuperviserData(BATCH_SIZE) 105 sess.run(train_op, feed_dict={inputs:x, labels:y}) 106 if i % (TRAIN_TIMES//10) == 0: 107 curLoss = sess.run(loss, feed_dict=test_feed_dict) 108 curAccuracy = sess.run(accuracy, feed_dict=test_feed_dict) 109 print('loss: %.6f accuracy: %.6f' % (curLoss, curAccuracy)) 110 print() 111 print('loss: %.6f' % sess.run(loss, feed_dict=test_feed_dict)) 112 print('accuracy: %.6f' % sess.run(accuracy, feed_dict=test_feed_dict)) 113

python

1loss: 0.628812 accuracy: 0.440000 2 3loss: 0.010268 accuracy: 0.440000 4 5loss: 0.005082 accuracy: 0.560000 6 7loss: 0.003374 accuracy: 0.560000 8 9loss: 0.002525 accuracy: 0.440000 10 11loss: 0.002017 accuracy: 0.560000 12 13loss: 0.001679 accuracy: 0.440000 14 15loss: 0.001438 accuracy: 0.440000 16 17loss: 0.001257 accuracy: 0.440000 18 19loss: 0.001117 accuracy: 0.440000 20 21loss: 0.001005 22accuracy: 0.440000

追記
ちょっとした実験をしてみました

python

1import tensorflow as tf 2import numpy as np 3from dataset.mnist import load_mnist 4 5訓練データ = [] 6正解ラベル = [] 7 8"""任意の比率で訓練データを作成する。 9 引数で100の内、正解ラベル[1,0]の訓練データを何個作るかを決める""" 10 11def 訓練_正解データ(value): 12 訓練データ = [] 13 正解ラベル = [] 14 for i in range(value): 15 x = np.random.randint(1, 3) * 0.01 16 入力値 = [ 17 np.random.randint(18, 81) * 0.01, 18 x, 19 np.random.randint(18, 81) * 0.01, 20 x, 21 ] 22 23 正解値 = [1, 0] 24 25 訓練データ.append(入力値) 26 正解ラベル.append(正解値) 27 #ここから残りの2割の訓練データを埋める 28 if i == value - 1: 29 while len(訓練データ) < 100: 30 x = np.random.randint(1, 3) * 0.01 31 y = np.random.randint(1, 3) * 0.01 32 33 if x == y: 34 continue 35 36 入力値 = [ 37 np.random.randint(18, 81) * 0.01, 38 x, 39 np.random.randint(18, 81) * 0.01, 40 y, 41 ] 42 43 正解値 = [0, 1] 44 訓練データ.append(入力値) 45 正解ラベル.append(正解値) 46 47 """念の為シャッフルする""" 48 シード値 = np.random.randint(0,1000) 49 50 np.random.seed(シード値) 51 np.random.shuffle(訓練データ) 52 53 np.random.seed(シード値) 54 np.random.shuffle(正解ラベル) 55 56 return [訓練データ, 正解ラベル] 57 58print(訓練_正解データ(100)) 59 60"""パラメーターの作成をする""" 61入力数 = 4 62中間数 = 100 63出力数 = 2 64 65入力ホルダ = tf.placeholder(tf.float32, [None, 入力数]) 66正解ホルダ = tf.placeholder(tf.float32, [None, 出力数]) 67キープ率 = tf.placeholder(tf.float32) 68 69重み1 = tf.Variable(tf.truncated_normal([入力数, 中間数], 70 stddev=tf.sqrt(2.0 /入力数))) 71バイアス1 = tf.Variable(tf.truncated_normal([中間数], 72 stddev=0.1)) 73 74重み2 = tf.Variable(tf.truncated_normal([中間数, 出力数], 75 stddev=tf.sqrt(2.0 / 中間数))) 76バイアス2 = tf.Variable(tf.truncated_normal([出力数], 77 stddev=0.1)) 78 79"""伝達処理をする""" 80一層目 = tf.matmul(入力ホルダ, 重み1) + バイアス1 81活性化1 = tf.nn.relu(一層目) 82ドロップアウト1 = tf.nn.dropout(活性化1, キープ率) 83二層目 = tf.matmul(ドロップアウト1, 重み2) + バイアス2 84出力層 = tf.nn.sigmoid(二層目) 85 86"""欠損関数を作成する。 87 欠損値がnanにならないようにtf.clip_by_valueで対策する""" 88欠損値バッチ = -tf.reduce_sum(正解ホルダ * tf.log(tf.clip_by_value( 89 出力層, 1e-10, 1.0), 90 ),axis=1) 91交差エントロピー = tf.reduce_mean(欠損値バッチ) 92 93"""正解率の作成""" 94真理値判定 = tf.equal(tf.argmax(出力層, 1), tf.argmax(正解ホルダ, 1)) 95正解率 = tf.reduce_mean(tf.cast(真理値判定, tf.float32)) 96 97"""確率的勾配下降の作成""" 98勾配下降 = tf.train.GradientDescentOptimizer(0.01).minimize(交差エントロピー) 99 100with tf.Session() as セッション: 101 セッション.run(tf.global_variables_initializer()) 102 103 for i in range(10000): 104 #学習させる比率を決める 105 n, m = 訓練_正解データ(30) 106 セッション.run(勾配下降, feed_dict={ 107 入力ホルダ:n,正解ホルダ:m,キープ率:1.0}) 108 109 if i % 100 == 0: 110 #テストデータの比率を決める 111 testn, testm = 訓練_正解データ(90) 112 out, sigmoid = セッション.run([二層目, 出力層], feed_dict={ 113 入力ホルダ:n,正解ホルダ:m, 114 キープ率:1.0}) 115 116 print(out) 117 print(sigmoid) 118 テスト = セッション.run(正解率, feed_dict={ 119 入力ホルダ:testn,正解ホルダ:testm, 120 キープ率:1.0}) 121 122 print(テスト)

前回のコードとの変更点は第一に、入力する値を小さくしています(0.01倍)
シグモイド関数に値を通しても、数値大小が変わる事はありません
しかし一定の数値を超えると、数値の大小に限らず1を返すようです。
当然そうなれば正常な判断が出来ません
試しに0.01倍を外してみるとわかると思います
画像を学習させる時も、普通は、その配列の中で最も大きい値で割る、平均の値で全ての配列を割るなどして値を小さくしますので、今回もそれに乗っ取ります

過学習対策のドロップアウト層も組み込んでいます。
一言で言えば、訓練データをニューラルネットに丸暗記をさせてはいけないのですが、一定確率でランダムなユニットを除去する事で、1ループだけ学習を停滞させ、丸暗記を防いでいます
ただし今回の場合は、特に効果は見られなかったので、キープ率は1.0のそのままにしてあります

そして実験用に、正解ラベルが[1,0]か[0,1]かを任意の比率で生成できる関数を作ってみました
自分の推測では、[1,0]が正解ラベルの時は出力層の一層目の値が大きくなるように変動し、
[0,1]が正解ラベルの時は出力層の二層目の値が大きくなるように変動するというものでした
比率を決める事で、本当にそうなるのかを確かめてみます

ではまず、上に張り付けたコードを実行してみてください。
このコードでは訓練データを3:7([1,0] ,[0,1])の比率で与えてみます
コードで言うとn, m = 訓練_正解データ(30)

テストデータは9:1の割合で与えます
testn, testm = 訓練_正解データ(90)

今回の場合ですと、自分の推測通りであれば、訓練データに[0,1]のデータを多く与えているわけですから二層目の値が大きくなるように学習をします
その結果テストデータで与える[1,0]が正解ラベルのデータに関しては全て不正解になるはずです
つまり9:1の割合でテストデータを与えると正解率は1割と推測できます

実際に実行してみると正解率が0.1になるのがわかると思います。

その他与える比率を変えてみてください
比率が傾いた方に出力層が大きくなり、そうでない方のテストデータは全て不正解になるはずです
また訓練、テストともに5:5で与えると多少のばらつきはあるものの50%に収束していきます

この実装が間違っていない限りは、真理値判定でも出来ない限りは、これに対応できる関数を作るのは難しく
、収束していった結果がこの正解率なのが伺えると思います

投稿2017/06/23 06:21

編集2017/06/28 06:44
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gittib_gittib

2017/06/27 09:52

回答ありがとうございます。大変参考になりました。 あれから色々試しているのですが、隠れ層を調整する事で対応できないかな、と考えています。 その層で、「2番目と4番目が同じ値である」とか「違う値である」という特徴を拾ってくれれば、このケースでも対応できるのではないでしょうか。 隠れ層はそのような特徴を見つけ出してくれるもの、というイメージを持っていたのですが、そんな簡単な話ではないですかね・・・
退会済みユーザー

退会済みユーザー

2017/06/27 15:01

このような形のネットワークを全結合層と言ったりしますが、この層の役割はそれに適応できる関数を作る、という方が正しいような気がします。例えば、与えられた入力値に対して、倍の数値を出力として出したいならパラメーター全体で×2になるような関数を作れば問題解決できるわけです 手書き数字などの人間がわからないような数字の配列も、何かしらの関数を作り分類してくれるわけです。 そういう意味では特徴を捉えて関数を作ってくれると言えるかもしれませんが本質ではない気がします また、隠れ層の役割は関数の柔軟性(表現力)を高める役割を担っているという認識です 一般的に、特徴を抽出する役目を担う部分は、畳み込み層と呼ばれる部分です。手書き数字であれば、画像全体を入力値として無作為に与えるのではなく、特徴を抽出した部分の値だけを与える事で、全結合層で関数が作りやすくなり、結果として認識精度があがるといった感じです 今回の問題の場合、全結合層だけで何とかしようと思ったら真理値判定に近いような関数でも作ってくれない限り、精度をあげるのは難しいように見えます...あくまでもイメージなので絶対にできないという自信があるわけではありませんが
gittib_gittib

2017/06/28 06:26

ありがとうございます。隠れ層は「関数の柔軟性を高める」という事を読ませていただき、ようやく理解できたように思います。 確かに、このケースでは2,4番目の値を座標と見立てて出力をプロットした場合、直線では区切れない。よって直線ではない区切り方が必要なので、その点において隠れ層が効果を発揮する、という事ですね。 まあ今改めると、質問に挙げたサンプルプログラムの隠れ層が適切に設計されているとは、思えないですが。 ともあれ、機械学習について大いに理解を進められましたので、上記回答をベストアンサーにさせていただきます。 ありがとうございました。
退会済みユーザー

退会済みユーザー

2017/06/28 06:42

既に理解されたみたいなので必要はないと思いますが、少し実験してみました。 まあすれ違いですね><
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問