質問: model.fit( x=x_train, y=y_train, batch_size=n_batch, epochs=n_t,validation_split=0.1, verbose=2, shuffle=True) # loss(訓練データの損失), acc(訓練データの正解率), al_loss(バリデーションセットの損失), val_acc(バリデーションセットの正解率) ``` 上記のように、fitメソッドを用いることによって > > Train on 54000 samples, validate on 6000 samples > > Epoch 1/10 > > - 2s - loss: 0.0349 - acc: 0.9892 - val_loss: 0.0286 - val_acc: 0.9912 > > > と結果が出たとします。ここでのlossとaccuracyについて、以下の2つの疑問についてお答えいただきたいです。 1epoch1/10の場合、訓練データ54000枚を1度だけ分類器の全層を通して54000枚分の特徴量を抽出し、学習済みのモデルを作成した後、訓練データとバリデーションデータを判別し、全枚数における正解の枚数を正答率として表しているのでしょうか。学習時だけ分類器の全ての層を通しているのか、判別時も同様に分類器を通るのか分かりません。 2学習モデルについては、畳み込み層で、教師付きの訓練データ画像一枚一枚の画像から特徴量を抽出して、全訓練画像からの特徴マップを作成し、その後flattenによって各特徴マップを1次元配列に平滑化し、全結合層によって、その1次元の特徴量を各クラスに分配して、各クラスの特徴量を保持するという認識でいますが、合っていますでしょうか。学習だけそういう特徴量を抽出するのか、判別でもそういう過程を経ているのか、イマイチ理解できませんので、ご教授頂けるか、有益なサイトおよび本など紹介いただけたら幸いです。 2つとも同じような質問ですが、独学に頼らざるを得ない環境のため、ご教授頂けたら幸いです。。。
回答: 私も機械学習について勉強中ですが、分かる範囲で答えさせていただきます。 1、2についてお答えする前に、まずCNN内で具体的にどのような操作が行われているのか説明します。 入力された画像が行列に変換され、その行列に各層(畳み込み層や全結合層などそれぞれの層)において、重みと呼ばれる言わば係数のようなものと掛け合わされます。(簡単に言うと、xを入力とするとy=wx+bみたいな形でyが次の層に渡されます。この場合、wが重み、bがバイアスと呼ばれるものです。バイアスは一次関数でいうただの切片です。)そして、全結合層において出力されたものと教師データを、損失関数を通して出た値がこの場合でいうlossですね。このlossを元に、AdamOptimizerと呼ばれるアルゴリズムによって各層の重み、バイアスを調整していきます。ここでいう”調整”というのが”訓練”であり、これがCNNでいう訓練の正体です。そして、1Epoch中でこれを54000枚の訓練データに対して行います。 さて、そろそろ質問に回答させていただきます。 1上記のように学習させるのは訓練データのみです。この訓練データで得たlossを元に、accを計算しています。また、バリデーションデータ(別名は検証データ)というものは、学習の進行度を可視化するデータです。つまり、1Epochで訓練データによって重みとバイアスを求めた後、その重みとバイアスを使って(AdamOptimizerを使った重みとバイアスの調整はせずに)バリデーションデータで出力を求めます。なぜかと言いますと、最終的には訓練を必要とせずに、画像を入力したら「この画像だね!」って分類して欲しいからです。なので、重みとバイアスを調整せず、ただ単にデータを通しただけの結果を確認する必要があります。 まとめますと、accは1Epoch中の訓練データの正答率、val_accは1Epoch中のバリデーションデータの正答率ですね。 2その認識で当たっていると思います。上記でも示した通り、学習では訓練データを、各層を通して最終的に重みとバイアスを調整します。54000枚かけた後、最終的に残った重みとバイアスを用いて、バリデーションデータを各層に通してみます。なので、訓練データ、バリデーションデータ共にモデルに1回は通しますね。重みとバイアスの調整、つまり訓練をするかしないのかの差です。これは、”訓練”、”検証”の違いです。 <質問に対する回答> 少し長くなりそうなのでこちらに記入いたします。 accが100%になるのでは?とのことですが、これについては重みとバイアスについて言い忘れていたことがありました。重要になってくるのは重みとバイアスの初期値です。これらは最初から決まっているわけではないので何かしら値を最初に決めてあげなければなりません。かといって、安直に「重み=0」なってことをすると、出力が0になってしまい学習どころではなくなってしまいます。(バイアスの初期値は0にすることが多いみたいです)そこで、何を使うかといいますと"乱数"を使います。正確には正規分布の乱数ですね。この正規分布の乱数を使用した重みとバイアスの初期化方法で「Xavierの初期化」というものがあります。その初期化についてはちょっと複雑になってしまうので今は触れないでおきます。なんか重みの初期化の方法があるんだなぁくらいに思っていてください。本題に入りますと、重みが乱数なわけですから分類したい画像をモデルにかけてもaccが100%になるなんてことはまずありえません。lossから重みとバイアスを調整することによってそれらを100%に近づけていくのです。 次にlossとaccの計算方法について簡単に説明します。 例えば犬、猫、猿の3種類が混ざった54000枚の画像を分類するとします。ここで、結果として何が出力されてほしいか?を考えてみると、犬の画像だったら犬、猫の画像だったら猫って出力してほしいわけです。つまり、出力の値の種類は「犬、猫、猿」の3種類になります。これはつまり、出力層からの出力は要素3つの配列になればいいよってことです。そして、一般的にはその配列の最大値をモデルの出力とします。(例えば出力が [0.13, 0.55, 0.32] だったとしたら、2番目の要素、この場合で言う"猫"がモデルの出力となります) ここで、上記で説明した出力が本当に元の画像とあっているのかを判定する必要があります。例えば、犬の画像をモデルに通して[0.13, 0.55, 0.32]が出力されたとします。しかし、理想的な出力は犬なので[1, 0, 0]です。一目見て値が全然違うことがわかりますね。この差が「loss」の正体です。正確には単なる「差」ではなく、分類問題では「交差エントロピー誤差」というものを使います。これも調べてみると良いと思います。今はlossを求める計算方法があるんだなぁってな感じで思っていてください。さらに求まった交差エントロピー誤差から「Adam」というアルゴリズムで重みとバイアスを調整していきます。Adam以外にもいろいろありますが、現時点ではAdamが一番良いみたいですね。 ここで、[1, 0, 0](※ここでいう[1, 0, 0]が"クラス"とか"ラベル"とかいうやつですね。また犬の画像を行列化したデータは単に入力データです。2つ合わせたものが訓練データです。)はどこから出てくるの?と思うかもしれませんが、これは自分で設定するしかありません。例えば、1番目の入力データが犬なら1番目のラベルは[1, 0, 0]、2番目の入力データが猫なら2番目のラベルは[0, 1, 0]のように別個でデータ群を作る必要があります。これを「ラベル付け」とか言ったりします。 しかし、ラベル付けを54000枚もやっていたら日が暮れてしまいますね?笑 なので、例えば犬の画像を1つのフォルダに集めて、そのフォルダに入っている訓練データのラベルは全部[1, 0, 0]だよ!みたいなことをやったりします。今回の場合はMNISTのデータセットなので、あらかじめラベル付けされていますし今は深入りしないことにしましょう。 いろいろ脱線してしまいましたが、こんな感じでlossを求めます。 最後にaccの求め方ですが、正直詳しい計算方法については僕もあんまりわかっていません笑 多分、ひと通り訓練データで学習した後、検証データでモデルを通したときの (正解数) / (正解数 + 失敗数) みたいな感じで求めるのかなと思います。 かなり長くなってしまい申し訳ございません^^;;