tf.kerasのクイックスタート-カスタム損失関数(1)

公式ウェブサイトのカスタム損失関数:ここ
公式ウェブサイトではKeras、カスタム損失提供するために使用する2つの方法があることがわかります

1.単純な平均二乗誤差

def custom_mean_squared_error(y_true, y_pred):
    return tf.math.reduce_mean(tf.square(y_true - y_pred))
    
model.compile(optimizer=keras.optimizers.Adam(), loss=custom_mean_squared_error)

この場合、y_true合計y_pred値は自動的に損失関数に渡され、実際の出力と予測された出力のデフォルトパラメータは2つしかないため、この方法は単純な損失関数にのみ適しています。あなたがに加えて使用が必要な場合y_truey_pred以外の他のパラメータの機能の喪失を、次のことができtf.keras.losses.Lossサブクラスを入力します。

1.1単純なケース

ここでも例として虹彩分類を取り上げています。シーケンスモデルを使用して必要なモデルを定義し、そのcompile中でカスタム損失関数を指定するだけです。シーケンスモデルで使用する損失関数はであるためsparse_categorical_crossentropy、2つの違いの簡単な記録を次に示します。

1.1.1 sparse_categorical_crossentropy&categorical_crossentropy

  • それはもしyあるone-hot encoding形式(すなわち、ワンホット符号ベクトル形式)、使用sparse_categorical_crossentropy
  • フォーマットではyなく整数の場合は、;をone-hot encoding使用しcategorical_crossentropyます。

アイリス分類のコードをコピーするだけです。

from sklearn.datasets import load_iris
x_data = load_iris().data  # 特征,【花萼长度,花萼宽度,花瓣长度,花瓣宽度】
y_data = load_iris().target # 分类

import tensorflow as tf
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(4, input_shape=(4,), activation='relu'))
model.add(tf.keras.layers.Dense(3, input_shape=(4,), activation='softmax'))
model.compile(
    optimizer="adam", 
    loss="sparse_categorical_crossentropy",  # 三分类的结果,已经需要使用独热码来表示。故而不能使用categorical_crossentropy
    metrics=['accuracy']
)
model.fit(x_data, y_data, epochs=100)

アイリスは3つのカテゴリーに分類されるため、3つのカテゴリーの結果です。むしろ非より0すなわち1結果、したがって、使用される必要がありますsparse_categorical_crossentropyしかし、その本質はクロスエントロピーです。クロスエントロピーの式は次のように表すことができます
。H(p、q)= − ∑ iy(xi)log(y ^(xi))H(p、q)=-\ sum_i y(x_i)log (\ hat y(x_i))H p q =Σy xl o g Y^x
y ^(xi)\ hat y(x_i)Y^xを表しXI X_Iをバツ予測分布、およびy(xi)y(x_i)y xトレーニングデータ内のカテゴリの確率分布を表します。
あなたは、クロスエントロピーを使用する必要がある場合は、に、私は、最終的な指標値のカテゴリに、とのために取得する必要があるためy_true、およびy_predこれらの2は、tf.Tensorオブジェクトの型が、その対応する値を取得する方法はありませんので、PROCLAIMに来ます失敗しました。代わりに、二乗損失関数を使用して以下を解決します。

from sklearn.datasets import load_iris
x_data = load_iris().data  # 特征,【花萼长度,花萼宽度,花瓣长度,花瓣宽度】
y_data = load_iris().target # 分类
# 转化为独热编码
y_data_one_hot = tf.one_hot(y_data, depth=3) # 3分类

import tensorflow as tf
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(4, input_shape=(4,), activation='relu'))
model.add(tf.keras.layers.Dense(3, input_shape=(4,), activation='softmax'))


def custom_mean_squared_error(y_true, y_pred):
    return tf.math.reduce_mean(tf.square(y_true - y_pred))


model.compile(
    optimizer="adam", 
    loss=custom_mean_squared_error,
    metrics=['acc']
)
history = model.fit(x_data, y_data_one_hot, epochs=300)


for key in history.history.keys():
    plt.plot(history.epoch, history.history[key])

ここに画像の説明を挿入します
もちろん、別の方法があります。それは、tensorflow提供されたクロスエントロピー損失関数を直接呼び出すことです。

# 转化为独热编码
y_data_one_hot = tf.one_hot(y_data, depth=3) # 3分类

import tensorflow as tf
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(4, input_shape=(4,), activation='relu'))
model.add(tf.keras.layers.Dense(3, input_shape=(4,), activation='softmax'))


def custom_mean_squared_error(y_true, y_pred):
    return tf.losses.categorical_crossentropy(y_true, y_pred)


model.compile(
    optimizer="adam", 
    loss=custom_mean_squared_error,
    metrics=['acc']
)
history = model.fit(x_data, y_data_one_hot, epochs=300)

または

from sklearn.datasets import load_iris
x_data = load_iris().data  # 特征,【花萼长度,花萼宽度,花瓣长度,花瓣宽度】
y_data = load_iris().target # 分类
# 转化为独热编码
#y_data_one_hot = tf.one_hot(y_data, depth=3) # 3分类

import tensorflow as tf
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(4, input_shape=(4,), activation='relu'))
model.add(tf.keras.layers.Dense(3, input_shape=(4,), activation='softmax'))


def custom_mean_squared_error(y_true, y_pred):
    return tf.losses.sparse_categorical_crossentropy(y_true, y_pred)


model.compile(
    optimizer="adam", 
    loss=custom_mean_squared_error,
    metrics=['acc']
)
history = model.fit(x_data, y_data, epochs=300)


for key in history.history.keys():
    plt.plot(history.epoch, history.history[key])

2.Lossクラスをインスタンス化します

同様に、クラスはから継承する必要がありtf.keras.losses.Loss、次に次の2つのメソッドを複製する必要があります。

  • __init__(self):損失関数の呼び出し中に渡されるパラメーターを受け入れます。
  • call(self, y_true, y_pred):ターゲットy_trueと予測モデルy_pred使用して損失モデルを計算します。

たとえば、公式Webサイトの場合:mse, 存在一个会抑制预测值远离 0.5

class CustomMSE(keras.losses.Loss):
    def __init__(self, regularization_factor=0.1, name="custom_mse"):
        super().__init__(name=name)
        self.regularization_factor = regularization_factor

    def call(self, y_true, y_pred):
        mse = tf.math.reduce_mean(tf.square(y_true - y_pred))
        reg = tf.math.reduce_mean(tf.square(0.5 - y_pred))
        return mse + reg * self.regularization_factor
        
model.compile(optimizer=keras.optimizers.Adam(), loss=CustomMSE())

比較的単純なため、虹彩分類の場合は設定されていません。しかし、上記の公式Webサイトの場合から、1つの問題も見られ
ます。損失関数を定義するためのここでの単純なインスタンス化サブクラスは、実際には、損失関数functionとして直接定義する上記と同様です。callパラメータまたは2つの値のみy_true渡しためy_pred、上部で大騒ぎする必要がありますが、さらに困難になります。
次の記事では、損失関数をカスタマイズするためのより柔軟な方法について説明します。実際、前のブログで言及されていました。つまり、複雑さと学習率と損失関数は次のようになります。

import tensorflow as tf
x = tf.random.normal([20, 2], mean=2, stddev=1, dtype=tf.float32)
y = [item1 + 2 * item2 for item1, item2 in x]
w = tf.Variable(tf.random.normal([2, 1], mean=0, stddev=1))

epoch = 5000
lr = 0.002
for epoch in range(epoch):
    with tf.GradientTape() as tape:
        y_hat = tf.matmul(x, w)
        loss = tf.reduce_mean(tf.where(tf.greater(y_hat, y), 3*(y_hat - y), y-y_hat))
    w_grad = tape.gradient(loss, w)
    w.assign_sub(lr * w_grad)

print(w.numpy().T) # [[0.73728406 0.83368826]]

おすすめ

転載: blog.csdn.net/qq_26460841/article/details/113614747