前提
tensorflow.kerasで
出力層の予測/教師最適カテゴリ(クラス)あるはその誤差を学習ごとに取得すること
または、それらを評価している関数名を知ること。(その関数の動作を調べてそれらを取得するように修正)
目的はカテゴリごとの正解率を評価すること。
keras公式ページのコールバックの説明
Writing your own callbacks
https://keras.io/guides/writing_your_own_callbacks/
には、出力クラスごとの誤差、もしくは最適クラス(softmax)の情報は見当たらないようです。
この情報を各学習ごとに知ることはできないでしょうか。
これができないようなので出力クラスを選択評価する処理のソースを見なければなりませんが、
どこにあるか探すのに苦労しています。
多分site_packages.kerasのmodel.fitやmodel.evaluateあたりと目星をつけましたが探しきれません。(先のzeroからシリーズ本ではほとんど見えていたので目的は果たせた)
最後の手段は、keras以下のすべての.pyファイルをつなげたtextファイルを生成するプログラムを別途つくりエディタで調べるなんてことも考えられますが・・。
こんなのありますけど、tensorflow 1.*に付いてのものなので、2.*でもできるのかどうか
https://qiita.com/shiita0903/items/838d50598cc28766f84e
こちらもご返事ありがとうございます。
完全には理解できかねていますけれど、求めているのは多分サイトのようなmetricsの種類ではなく、
”正解ラベルのテンソルと予測ラベルのテンソルの2つを引数とし” とあることから推理するに、
予測ラベルのテンソルと言う意味を、pred-lbl(1,サンプル数)のテンソルと言う意味ならば、
まさに今求めている物です。これがcallbackなどで参照できれば良いのですが。公式サイトのcallback項目を見た限りではなかったように思います。
全体的なmtricsではなくラベルごとの正解数を知りたいのです。
そのためにはバッチ学習終了後(epoch単位で)改めてバッチなしの全サンプルの推論だけを行って、これを評価します。
zeroからシリーズでは、中身が見えるのでできました。
余談です。jbpb0さんの自己画像はアオサギですね。私もバードウオッチを少しやっています。花の識別を画像認識でやっているところがあるようですが(最近発見)、鳥もやれるのかな??関係なければすみません。
余談ついでに、ラベルごとの正解数の意味は、例えば鳥画像と花画像の画像認識があって、それぞれが正解であれば万々歳ですが、鳥と花の区別ができればよしとするようなことに相当します。
私が紹介したWebページの「TensorBoard」に、
「クラスごとのAccuracyやMacro Precisionなどがちゃんと表示されていますね!」
と書かれてます
質問に
「目的はカテゴリごとの正解率を評価すること。」
とあります
・私が紹介したページの「クラスごとのAccuracy」
・質問の「カテゴリごとの正解率」
が同じ意味だと思い、紹介しました
ご紹介のページは確かに同じ意味でしたが、説明不足でしたが、必要なことはカテゴリーごとの正解数とそのカテゴリーの数であり、それを後処理で利用できるデータの形で取得することであることと、tensorbordは現段階では利用しないつもり(将来は見るかも)でしたので、調査することをしませんでした。その旨をお知らせしなかったことはお詫びします。
その後さらに調べますと、(model.)output.data()のような形式で見るような記事をみまして、それの公式ページやQ&Aなどを探しているところです。そのようなメソッドもあっても不思議ではないですね。
すべてのクラスとメソッドやプロパティの説明があればいのですが。
どなたかが言っていましたが、ネット検索のコツなどがあるようです。
ようやく環境の修復も終わりましたので合わせて調べるところです。
> 花の識別を画像認識でやっているところがあるようですが(最近発見)、鳥もやれるのかな??
こういうのですかね
https://apps.apple.com/jp/app/birdscan-identify-bird/id1614800047
https://igamemom.com/apps-about-birds/
お! 今の世の中こんなのがあるのだ。すごい。AIとあるのがNN検索らしく、数秒で答えが出るとか、ほかはイメージ知識データベースのようですね。
花は、MNISTのようなデータがあるので、それ用と思いました。
実は3-10年前は両方とものめりこんでいましたが、今のハードの向上からすると、やってみたくなるような情勢ですね(今となっては余裕がありませんが)
先の余談失礼しました。
https://qiita.com/shiita0903/items/838d50598cc28766f84e
の「準備」以降のコードを全部そのままgoogle colabにコピペしてから、下記を変更
from keras.utils import to_categorical
↓
from keras.utils.np_utils import to_categorical
model.fit(x_train, y_train,
validation_data=(x_test, y_test),
batch_size=400,
epochs=50,
callbacks=[TensorBoard()])
↓
history = model.fit(x_train, y_train,
validation_data=(x_test, y_test),
batch_size=400,
epochs=50)
コードの最後に下記を追加して実行
print(history.history.keys())
print(history.history['acc-0'])
print(history.history['acc-9'])
print(history.history['val_acc-0'])
print(history.history['val_acc-9'])
上記の結果表示で、たとえば「print(history.history['acc-0'])」の結果には50個の数値が並んでますが、これは数字「0」画像の学習データの各エポックでの正解率です
同様に、「print(history.history['val_acc-9'])」の結果の50個の数値は、数字「9」画像のvalデータの各エポックでの正解率です
他にも取得できるものがたくさんあり、それらは「print(history.history.keys())」の結果を参照したら分かります
上記のようにして、model.fit()の各エポックでの「クラスごとのAccuracy」等を数値で取得できることが確認できましたが、これは
> 後処理で利用できるデータの形で取得
にはならないでしょうか?
なお、コードを実行して確認した時のtensorflowのバージョンは、2.8.2+zzzcolab20220719082949でした
参考にしたWebページのコードをたいして変更しなくても、tensorflow 2.*で動きました
詳しく検討いただきありがとうございます。
こちらもご返事いただいていたのを見逃し、すみませんでした。
自己解決投稿した折に気が付きました。
詳しくは拝見できなかったですが、自己解決した方法とは多分異なると思います。
折角ですので、自己解決した具体的なコードを提示します。
インデントが反映されているとよいですが。
ポイントは
・model関数の戻り値に出力値の値が反映されていることを利用する。
・コード中にある半正解数(ラベルの半数の範囲にあれば半正解とする。勝手な命名)を計算する。
ただし、提示のコードはいかにも非python風で力任せですので、もっとスマートなコードがあるのでは思います。ただ、この計算はepoch終了ごとで良いので、まあいいかなと。
def onehot2no(onehot):
for n in range(p_out):
if(onehot[n]>0.5):
return n
return -1
def train_step(x, t):
outputs = model(x, training=True) # モデルに入力して順伝搬の出力値を取得
train_accuracy(t, outputs)
# 求めたい正解数の計算
ct=[0 for ot in range(p_out)]
win=[0 for ot in range(p_out)]
win2=[0 for ot in range(p_out)]
for bat in range(batch_size):
maxv=0
maxot=0
print("outputs",outputs[bat,])
for ot in range(p_out):
if outputs[bat,ot] > maxv:
maxv = outputs[bat,ot]
maxot = ot
no = onehot2no(t[bat]) #onehotlabel をlaberスカラーに変換
print("t_bat", no)
ct[maxot] += 1
if maxot==no:
win[maxot] += 1 #カテゴリごとの正解数
if no<p_out/2:
if maxot < p_out/2 :
win2[maxot] +=1 #カテゴリごとの半正解数
elif no>p_out/2:
if maxot > p_out/2:
win2[maxot] += 1 #カテゴリごとの半正解数
print("train bat",bat,"max",maxv,maxot,"t",t[bat])
print("train ct ",ct)
print("train win ",win)
print("train win2",win2)
return ct,win,win2
この欄への投稿は先頭のスペースが無視されるので、見にくく済みません。
「train_step()」の使い方を教えてください
kerasでの学習では、データを用意して、モデルを定義してから、
model.compile(...
model.fit(...
のようにしてモデルの学習を行いますが、その流れの中にどのようにして「train_step()」を組み込むのでしょうか?
train_step_callback = keras.callbacks.LambdaCallback(on_epoch_end=lambda epoch,logs: train_step(x, t))
みたいなのを、「model.fit()」で
「callbacks=[train_step_callback]」
のように指定するのでしょうか?
>「train_step()」の使い方を教えてください
model.compile(...
model.fit(...
このような記述のサンプルも見たことがありますが、よくわかりません。
これは件の本の5.5章をべs-スにしたのですが、コードの抜粋を提示します。
これでいかがでしょうか。ちなみにこれはMLPとなっていてCNNではありません。
```
'''
1. データセットの読み込みと前処理 shuwa 5.5
'''
# tensorflowのインポート
import tensorflow as tf
import numpy as np
import sys
import math
'''
2. モデルの定義
'''
class MLP(tf.keras.Model):
def __init__(self, hidden_dim, output_dim):
super().__init__()
self.fc1 = tf.keras.layers.Dense(hidden_dim, activation='relu')
self.dropout = tf.keras.layers.Dropout(0.5)
self.fc2 = tf.keras.layers.Dense(output_dim, activation='softmax')
def call(self, x, training=None):
'''MLPのインスタンスからコールバックされる関数
Parameters: x(ndarray(float32)):訓練データ、または検証データ
Returns(float32): MLPの出力として要素数3の1階テンソル
'''
x = self.fc1(x) # 第1層の出力
if training: # 訓練モードのときdropout
x = self.dropout(x)
x = self.fc2(x) # 出力層の出力
return x
'''
3. 損失関数とオプティマイザーの生成
'''
import tensorflow as tf
# マルチクラス分類のクロスエントロピー誤差を求めるオブジェクト
loss_fn = tf.keras.losses.CategoricalCrossentropy()
# 勾配降下アルゴリズムを使用するオプティマイザーを生成
optimizer = tf.keras.optimizers.SGD(learning_rate=0.1)
'''
4. 勾配降下アルゴリズムによるパラメーターの更新処理を行うtrain_step()関数
'''
# 損失を記録するオブジェクトを生成
train_loss = tf.keras.metrics.Mean()
# カテゴリカルデータの精度を記録するオブジェクトを生成
train_accuracy = tf.keras.metrics.CategoricalAccuracy()
def onehot2no(onehot):
for n in range(p_out):
if(onehot[n]>0.5):
return n
return -1
def train_step(x, t):
'''学習を1回行う
Returns:
ステップごとのクロスエントロピー誤差
'''
# 自動微分による勾配計算を記録するブロック
with tf.GradientTape() as tape:
# 訓練モードをTrueに指定し、
outputs = model(x, training=True) # モデルに入力して順伝搬の出力値を取得
#print("outputs",outputs.shape)
tmp_loss = loss_fn(t, outputs) # 出力値と正解ラベルの誤差
# tapeに記録された操作を使用して誤差の勾配を計算
grads = tape.gradient(
tmp_loss, # 現在のステップの誤差
# バイアス、重みのリストを取得
model.trainable_variables)
# 勾配降下法の更新式を適用してバイアス、重みを更新
optimizer.apply_gradients(zip(grads,
model.trainable_variables))
train_accuracy(t, outputs)
# 以下は半正解数などを計算する処理
return ct,win,win2
'''
8.モデルを生成して学習する
'''
from sklearn.utils import shuffle
epochs = 100
model = MLP(256, p_out) # 隠れ層256ユニット、出力層10ユニットのモデルを生成
# 学習を行う
for epoch in range(epochs):
x_, y_ = shuffle(tr_x, tr_y, )
```
# 1ステップにおける訓練用ミニバッチを使用した学習
for step in range(tr_steps):
ct,win,win2 = train_step(x_[start:end], y_[start:end])
```
MLPの次にcnnを調べていて、ご質問の意味がわかりました。
CNNでは
model.compile(...
model.fit(...
model.evaluate()
とかやっているのですね。
この場合は、確かに予測出力値は直ちには見れないのですね。それで、当初のこの質問をしたのだと思います。
それで、調べていきますと
pred=model.predict()
というのがあって、サンプルコードでprtint(pred)とすると、求めているカテゴリーごとの出力値が出ました。
ですので
pred=model.pred(x_train)
pred =model.pred(x_test)
などとすればよさそうにみえます。これぐらいは本来あって当然な機能と思います。
それで、kerasのcnnを希望を持って進めることができそうですが、これはこれで問題に行き当っています。
修正
pred=model.predict(x_train)
pred =model.predict(x_test)
物体・画像認識と時系列データ処理入門 [TensorFlow2/PyTorch対応第2版]
https://www.shuwasystem.co.jp/book/9784798063546.html
で、cnnは
・6.2 TensorFlowスタイルによるCNNの構築
・6.4.3 TensorFlowスタイルによるプログラミング
・7.1.4 TensorFlowスタイルでプログラミングしたCNNに飛行機、自動車、イヌ、ネコなどの10種類の画像を認識させてみる
・7.2.5 画像を拡張処理して精度90%を達成する(TensorFlow)
が、
・5.5 TensorFlowスタイルによるニューラルネットワークの構築
と同じやり方です
・339ページの下
・362ページの上
を見ると、6.2,と6.4.3では「train_step()」とかは5.5のを使うと書かれてます
7.1.4では399ページからコードが書かれてますが、5.5のと比べても、ほとんど同じです
463ページの下〜464ページの上を見ると、7.2.5では「train_step()」とかは7.1.4のを使うと書かれてます
339ページ以下の件はその通りでしたが、どうもご指摘の意図がわかりません。
6.2は自前datasetsではまだで、これからですが、そのあたりを含めてサンプルプログラムの構成は統一が取れているようで、そうでもない部分もあり戸惑うときがあります。
私の解決策の投稿はmodel.predict(モデル)につきます。
> ご指摘の意図がわかりません。
6.2, 6.4.3, 7.1.4, 7.2.5を紹介したのは、
> MLPの次にcnnを調べていて、ご質問の意味がわかりました。
CNNでは
model.compile(...
model.fit(...
model.evaluate()
とかやっているのですね。
と書かれたからです
mlpだから、cnnだから、ではなく、mlpもcnnもその書籍では
・TensorFlowスタイル
・Kerasスタイル
・PyTorch
の三種類のコードが記載されてます、と述べただけです
・5.6 Kerasによるニューラルネットワークの構築
では、mlpですが「model.fit()」を使う一般的なkerasのやり方でコードが書かれてます
cnnだから「model.fit()」を使ってる、というわけではありませんよね
> 調べていきますと
pred=model.predict()
というのがあって、サンプルコードでprtint(pred)とすると、求めているカテゴリーごとの出力値が出ました。
「model.fit()」を使う一般的なkerasのやり方の場合は、学習の各エポックで「クラス別の正解率」の様な標準では用意されてない計算をするには、「model.fit()」の内部でその計算がされるように設定する必要があると思います
私が最初のコメントで紹介した
https://qiita.com/shiita0903/items/838d50598cc28766f84e
でやってる「model.compile()」の「metrics=」で指定する方法や、ちょっと上のコメントで質問した「model.fit()」の「callbacks=」で指定する方法は、どちらも上記のための設定方法です
私が勘違いしてて、そのような設定をしなくても、「model.fit()」を使う一般的なkerasのやり方の場合で、学習の各エポックでの「クラス別の正解率」が計算できるのでしょうか?
もっと簡単にやれる方法があるなら教えてください
「model.fit()」での学習が全て終わった後に一回だけ「クラス別の正解率」を計算すればいいのなら、そこで
> pred=model.predict(x_train)
pred =model.predict(x_test)
を実行すればいいですが、質問の
> この情報を各学習ごとに知ることはできないでしょうか。
の「各学習」は、各エポックのことですよね?
(そう思って、ずっと書いてました)
誤解の無い様に書いておきますが、「model.fit()」を使う一般的なkerasのやり方と、書籍5.5の様なやり方と、どちらが良いとか、こうすべきとか思ってるのではありません
「model.fit()」を使う一般的なkerasのやり方は簡単に書けますが、詳細が隠蔽されてて融通が効かないので、学習過程を細かくカスタマイズしたい場合は、書籍5.5の様なやり方の方がやりやすくなります
公式のドキュメントにも、そんな様なことが書かれてます
https://tensorflow.classcat.com/2021/01/16/tf24-guide-keras-writing-a-training-loop-from-scratch/
詳しく幾度もご説明いただいたのですが、現在の実力ではその内容を十分に理解できませんでしたので、あるいは頓珍漢なことを申し上げたかも知れません。そうであればお詫びします。そのいきさつはだいぶわかりました。
特記事項として
・model.fit() と model.predict()とは いずれかの選択ではないですよね。predictはfitのオプションのような位置づけですね。
・詳細が隠蔽されてて融通が効かない・・・のことはその通りだと思います。融通を効かせてかつ簡単なのがよいですが。理解が進めば使いわけられるかも。書籍等はブラックボックス的になり中身が見えないのが問題です。その点ゼロからシリーズ本はそれに期待して入手しましたがそこまでは進まず。
・各学習ごとは、epochごとの積りです。model.predictではそれがきないのかしら。全epoch終了後のみであれば面白くない。いまから調べるところです。
自前データによる6.1ができたところです。(predictは未実装)苦労します。
> この欄への投稿は先頭のスペースが無視される
ここではなくて回答なら、
```python
(pythonコード)
```
と書けばインデントが反映されますので、「自己解決」の回答を編集して、ぜひ解決したコードを追記してください
全部書くのが面倒なら、書籍のコードとの相違点を書くだけでも
(その場合は、書籍名と、元コードが載ってるのが何ページかも書いた方がいいです)
そうすれば、同様なことで悩んで、検索してこの質問を見つけた人の参考になります
https://teratail.com/tour
に
「質問・回答によって生まれたコンテンツを、同じ問題を持った人に最適な形で届けます。」
と書かれてるように、「teratail」にはそのような役割もありますので
私もそのコードを実行してみたいですし
回答1件
あなたの回答
tips
プレビュー