ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

駄目駄目マン

まだスランプというか、うまくいっていないマン。振り返りたい

駄目駄目なこと

  • 毎日がギリギリ
    • ギリギリなのが悪いのではなくその上進捗がでていないのが駄目駄目

原因

  • 脳死している気が...
    • 自分の仕事にプライドを持っていないような
    • 年齢重ねるにつれ、プライドがでてきたなと思いきや逆にプライドがなくなっている気が
    • その証拠に何度も似たような失敗していると思う
    • これはやばい. 勝手に疲弊して死んでいくパターン
  • 実力が足りない
    • 永遠の課題

解決案

  • 1人で仕事しない
    • 人の意見入ると一点張りになりづらいのでいいかなって思う
    • 資料とかよく突っ込まれるのでレビューしてもらうのもいいかと
  • 一回死ぬ(論理/n回目)
    • 今実力が足りないのはわかっているので勉強し続けるしかない
    • しかし時間はないので睡眠削るとかしか手がない
    • だがしかし経験上長くは続かないので細かい時間使ってなんとかするしかない

こういう考えもだめかな?(そもそも無理するって現実的なの?的な
実はこれも逃げなのでは?

うーむ難しい

希望

  • プライドを持つ
    • オレがやるなら絶対成功させる的な

まずはこれじゃないかなー

Tensorflow2でKerasみたいな保存の仕方すると死ぬ

タイトルはてきとーにつけたので正しくはない

Colaboratoryで遊んでいるとき、他notebookで保存したモデルを読み込みたかった.

import tensorflow as tf


model = None  # 学習済みのモデルを想定
# Model is the full model w/o custom layers
model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss=tf.keras.losses.CategoricalCrossentropy(),
              metrics=['accuracy', tf.keras.metrics.AUC(name='auc')])

model.save('/content/drive/My Drive/model.h5')

保存に成功したので、別notebookでロードする.

model = tf.keras.models.load_model('/content/drive/My Drive/model.h5')

ValueError: Unknown entry in loss dictionary: class_name. Only expected following keys: ['xxx']

??????

どゆことと、調べたら下記issueがヒット

github.com

i find the reason, in my code: loss_object=tf.losses.SparseCategoricalCrossentropy() model.complie(loss=loss_object, optimizer="sgd")

it raise the error.

the i change my code to model.complie(loss="sparse_categorical_crossentropy", optimizer="sgd")

it is ok

なんだと・・・・

いや、それはそれでいいんだけど、カスタムlossとかの場合はどうなるんじゃろ???

それはさておき、issue出した人はPRも出していた

github.com

これをコピペしてロードしたら動いた

しかしどうしようかな。。。

Tensorflow2系で指定したレイヤーから勾配を取得したい場合

ハマった

import tensorflow as tf

# fine tuningしたいのでvgg16のモデルをロード
vgg16 = tf.keras.applications.VGG16(include_top=False, input_shape=(100, 100, 3))

for l in vgg16.layers:
    l.trainable = False

x = tf.keras.layers.Flatten()(vgg16.output)
x = tf.keras.layers.Dense(512, activation='relu')(x)
output = tf.keras.layers.Dense(5, activation='softmax', name='last_output')(x)
model = tf.keras.Model(inputs=vgg16.inputs, outputs=output, name='model')

model.compile(optimizer='adam', loss='categorical_crossentropy')
model.summary()

これで準備おk

Grad-Camとよばれる、CNNモデルがどこに着目して分類しているのかを確認する手法がある。

ネットで探せばKerasやらなんやらでみんなコードを載せているが、2系でやり方載っておらずドキュメントみながら試してた

import numpy as np


images = np.ones((1, 100, 100, 3))

# 予測クラスの算出
predictions = model.predict(images)
class_idx = np.argmax(predictions[0])
class_output = model.output[:, class_idx]

# 勾配を取得するための準備
layer_output = model.get_layer('last_output').output

# 勾配取得
grands = tf.gradients(class_output, layer_output)[0]

↑の最後のコードを実行するとエラーになる

RuntimeError: tf.gradients is not supported when eager execution is enabled. Use tf.GradientTape instead.

tf.GradientTape 使えって????

使ってみる

with tf.GradientTape() as tape:
    print(tape.gradient(class_output, layer_output))

None

orz

わかった!Kerasのチュートリアル多いから、TensorflowからKerasを呼んで使ってみる

grands = tf.keras.backend.gradients(class_output, layer_output)[0]

RuntimeError: tf.gradients is not supported when eager execution is enabled. Use tf.GradientTape instead.

orz

どないせーとって思っていておおハマりして5時間.

Tensorflow2は、1系ではデフォだった、Graph modeが扱える. Eagerじゃないmodeで取得できないか試してみた.

g = tf.Graph()
with g.as_default():
    grads = tf.gradients(class_output, layer_output)[0]

grads

<tf.Tensor 'gradients/strided_slice_3_grad/StridedSliceGrad:0' shape=(None, 5) dtype=float32>

やったぜ!!!!

あっているかわからんが、とりあえず取れたので良しとする.

Tensorflow2系のサブクラスモデルの構造は保存できない

import tensorflow as tf


class MyModel(tf.keras.Model):
  def __init__(self, output_node):
    super(MyModel, self).__init__()
    self.d1 = tf.keras.layers.Dense(128, activation='relu')
    self.d2 = tf.keras.layers.Dense(output_node, activation='softmax')
  
  def call(self, x):
    x = self.d1(x)
    return self.d2(x)

こんな簡単なモデルを用意します。

model = MyModel(output_node=10)
model.compile(loss='sparse_categorical_crossentropy', optimizer=tf.keras.optimizers.RMSprop())
model.build(input_shape=(32, 10))
model.summary()

モデルをビルドして構造確認するとこんな感じ

Model: "my_model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                multiple                  1408      
_________________________________________________________________
dense_1 (Dense)              multiple                  1290      
=================================================================
Total params: 2,698
Trainable params: 2,698
Non-trainable params: 0
_________________________________________________________________

Keras触っているならなんら普通な流れ.

問題はここから。

tf.keras.experimental.export_saved_model(model, 'path_to_saved_model', serving_only=True)
# W0506 10:36:19.523535 140296071452544 saved_model.py:124] Skipped saving model JSON, subclassed model does not have get_config() defined.

ドキュメント確認すると↑のコードで保存ができるらしい。が、しかし

model2 = tf.keras.experimental.load_from_saved_model('path_to_saved_model')
# NotFoundError: path_to_saved_model/assets/saved_model.json; No such file or directory

???

前のコードをよくみると W0506 10:36:19.523535 140296071452544 saved_model.py:124] Skipped saving model JSON, subclassed model does not have get_config() defined. と、書いてあった。なるほど。。。

で、ここから下記対応したが駄目だった

  • サブクラスで、 get_config を実装する

  • pickle で保存できないか確認してみる

    • TypeError: can't pickle weakref objects なるほど。。。

というわけでうまくいかんかったので、 model.summary() の結果を保存することにした。。。

これいつか対応してくれるとうれしいな

保存できる方法について

サブクラスを使わずに、KerasのSequentialと、Functional APIを使えばいける。

Sequential

model = tf.keras.Sequential([
    tf.keras.layers.Input(shape=(10,), batch_size=32),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(loss='sparse_categorical_crossentropy', optimizer=tf.keras.optimizers.RMSprop())
model.build(input_shape=(32, 10))
tf.keras.experimental.export_saved_model(model, 'path_to_saved_model', serving_only=True)

Functional API

inputs = tf.keras.Input(shape=(32, 10))
x = tf.keras.layers.Dense(128, activation='relu')(inputs)
predictions = tf.keras.layers.Dense(10, activation='softmax')(x)
model = tf.keras.Model(inputs=inputs, outputs=predictions)

model.compile(loss='sparse_categorical_crossentropy', optimizer=tf.keras.optimizers.RMSprop())
model.build(input_shape=(32, 10))
tf.keras.experimental.export_saved_model(model, 'path_to_saved_model', serving_only=True)