前のtf.kerasクイックスタート-カスタム損失関数(1)では、サブタイプをインスタンス化するための損失関数の2つのカスタムメソッドについて説明し函数式
、継承しましたtf.keras.losses.Loss
。ただし、記事の最後で、これら2つの方法には実際には大きな制限があることも述べたため、この記事では、損失関数をカスタマイズする別のより柔軟な方法について説明します。
で学習率&ロス機能&の複雑さ:記事、このプロセスを達成するために、簡単な例が取り付けられている
損失関数の区分的関数として定義されています。予測値が真の値よりも大きい場合、モデルには適さないと考えられます。つまり、
f(y ^、y)= {3(y ^ − y)y ^ ⩾yy− y ^ y ^⩽yf (\ hat y、y)= \ left \ {\ begin {matrix} 3(\ hat yy)\ \ \ \ \ hat y \ geqslant y \\ y- \ hat y \ \ \ \ \ hat y \ leqslant y \ end {matrix} \ right。f (Y^、および)={{
3 (Y^−および) Y^⩾YY−Y^ Y^⩽そして
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]]
ここでは、まだ虹彩の分類を例として取り上げており、ここで変更します。前述のカスタマイズModel
などを組み合わせLayer
ます。
class MyLayer(tf.keras.layers.Layer):
def __init__(self, _shape, activation='relu'):
super(MyLayer, self).__init__()
self._shape = _shape
self.activation = activation
def build(self, input_shape):
self.kernel = self.add_weight("kernel", shape=(int(input_shape[-1]), self._shape),initializer='random_normal',trainable=True)
self.bias=self.add_weight(shape=(self._shape,),initializer='random_normal',trainable=True)
def call(self, inputs):
out = tf.matmul(inputs, self.kernel) + self.bias
if self.activation == 'relu':
out = tf.nn.relu(out)
if self.activation == 'softmax':
out = tf.nn.softmax(out)
return out
import matplotlib.pyplot as plt
%matplotlib inline
import tensorflow as tf
from sklearn.datasets import load_iris
# 训练集和测试集的划分
from sklearn.model_selection import train_test_split
x_data = load_iris().data # 特征,【花萼长度,花萼宽度,花瓣长度,花瓣宽度】
y_data = load_iris().target # 分类
x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.30, random_state=42)
class MyModel(tf.keras.Model):
def __init__(self, hidden_shape, output_shape):
super(MyModel, self).__init__()
self.layer1 = tf.keras.layers.Dense(hidden_shape, activation='relu')
self.layer2 = tf.keras.layers.Dense(output_shape, activation='softmax')
def call(self, inputs):
h1 = self.layer1(inputs)
out = self.layer2(h1)
return out
model = MyModel(hidden_shape=4, output_shape=3)
train_loss = tf.keras.metrics.Mean(name='train_loss')
train_acc = tf.keras.metrics.CategoricalAccuracy(name='train_acc')
def train():
with tf.GradientTape() as tape:
# 1. 前向传播计算y
out = model(x_train)
y_train_one_hot = tf.one_hot(y_train, depth=3)
# 2. 定义Loss
loss = tf.losses.categorical_crossentropy(y_train_one_hot, out)
gradients = tape.gradient(loss, model.trainable_variables) # 反向求导
tf.optimizers.Adam().apply_gradients(zip(gradients, model.trainable_variables)) # 参数更新
train_loss(loss) # train_loss.update_state(loss)
train_acc(y_train_one_hot, out) # train_acc.update_state(y_train_one_hot, out)
history = dict()
for epoch in range(300):
train_loss.reset_states()
train_acc.reset_states()
train()
try:
history['epoch'].append(epoch+1)
except:
history['epoch'] = [epoch+1]
try:
history['loss'].append(train_loss.result())
except:
history['loss'] = [train_loss.result()]
try:
history['acc'].append(train_acc.result())
except:
history['acc'] = [train_acc.result()]
template = 'Epoch {}, loss: {}, acc: {}'
print (template.format(epoch+1, train_loss.result(), train_acc.result()))
for key in history.keys():
if key != 'epoch':
plt.plot(history['epoch'], history[key])
コンテンツリファレンス:TensorFlow2.0カスタム損失関数