【问题标题】:How do I add noise to the weights when calculating the loss with Keras?使用 Keras 计算损失时,如何在权重中添加噪声?
【发布时间】:2020-12-13 23:45:20
【问题描述】:

我是 Keras 的新手,正在尝试自定义我在 Keras 中的训练步骤。

问题:

  1. 自定义训练循环时如何在 Keras 中使用 weights_right=weights- (lr+alpha)*gradients 创建新变量 weights_right?
  2. 如何以权重作为形式参数前馈 NN?我可以像下面的代码那样自定义 Keras 中的转发功能吗?

背景:

在随机梯度下降算法中,在前馈一个小批量数据并获得这个小批量数据的梯度后,我想扰动权重并创建一个名为 weights_right weights_righ t= weights-(lr+alpha)*gradients 的新变量(alpha 是一个常量) 然后用 weights_right 前馈 NN 以获得新的损失。

python中的部分代码如下:

class Network(object):
    def __init__(self, sizes):
        self.num_layers = len(sizes)
        self.sizes = sizes
        self.weights = [np.random.randn(y,1) for y in sizes[1:]]
        self.biases = [np.random.randn(y,x) for x, y in zip(sizes[:-1], sizes[1:])]
    def feedforward(self, a, weights=None, biases=None):
        """Return the output of the network if ``a`` is input."""
        if weights is None:
            weights=self.weights
        if biases is None:
            biases=self.biases
        #!!! Note the output layer has no activation for regression.
        for b, w in zip(biases[:-1], weights[:-1]):
            a = sigmoid(np.dot(w, a)+b)
        a=np.dot(weights[-1],a)+biases[-1]
        
        return a
    #-----------------------------------
    # The following is the important one.
    #-----------------------------------
    def customSGD():
        for epoch in range(epochs):
            random.shuffle(training_data)
            mini_batches= [training_data[k:k+mini_batch_size] for k in range(0, len(training_data), mini_batch_size)]
            for mini_batch in mini_batches:
                gradients_on_mini_batch = get_gradients(mini_batch)
                #---------------------------------------
                # The following two steps are what 
                # I would like to archive in Keras
                #---------------------------------------
                # Creat new variable called weights_right

                weights_right = weights-(lr+alpha)*gradients_on_mini_batch

                # feed the NN with weights_right, note that the params 
                #in current NN are still weights, not weights_right.

                pred_right = feedforward(training_data, weights_right)
                loss_right = loss_func(pred_right, training_labels)
                ......

                # update weights
                weights = weights-lr*gradients_on_mini_batch          

以上代码主要来自网书Michael Nielsen

任何帮助将不胜感激。非常感谢!

【问题讨论】:

  • @Andrey。嗨,安德烈,非常感谢您的回复。我会重写我的问题。其实我找了很久,也没有很清楚如何在 Keras 中执行。但我知道如何使用 numpy 在 Python 中编写代码。无论如何,非常感谢!

标签: python tensorflow keras neural-network


【解决方案1】:

在自定义训练循环中,您可以对梯度和权重做任何您喜欢的事情。

@tf.function
def train_step(inputs, labels):
    with tf.GradientTape() as tape:
        logits = model(inputs)
        loss = loss_object(labels, logits)

    weights = model.trainable_variables
    # add manipulation of weights here
    gradients = tape.gradient(loss, weights)
    opt.apply_gradients(zip(gradients, model.trainable_variables))
    train_loss(loss)
    train_acc(labels, logits)

这是完整的运行示例:

import tensorflow as tf
from tensorflow.keras import Model
from tensorflow.keras.layers import Dense
from sklearn.datasets import load_iris

X, y = load_iris(return_X_y=True)

dataset = tf.data.Dataset.from_tensor_slices((X, y)).shuffle(150)

train_dataset = dataset.take(120).batch(4)
test_dataset = dataset.skip(120).take(30).batch(4)


class DenseModel(Model):
    def __init__(self):
        super(DenseModel, self).__init__()
        self.dens1 = Dense(8, activation='elu')
        self.dens2 = Dense(16, activation='relu')
        self.dens3 = Dense(3)

    def call(self, inputs, training=None, **kwargs):
        x = self.dens1(inputs)
        x = self.dens2(x)
        x = self.dens3(x)
        return x


model = DenseModel()

loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

train_loss = tf.keras.metrics.Mean()
test_loss = tf.keras.metrics.Mean()

train_acc = tf.keras.metrics.SparseCategoricalAccuracy()
test_acc = tf.keras.metrics.SparseCategoricalAccuracy()


opt = tf.keras.optimizers.Adam(learning_rate=1e-3)


@tf.function
def train_step(inputs, labels):
    with tf.GradientTape() as tape:
        logits = model(inputs)
        loss = loss_object(labels, logits)

    weights = model.trainable_variables
    # add manipulation of weights here
    gradients = tape.gradient(loss, weights)
    opt.apply_gradients(zip(gradients, model.trainable_variables))
    train_loss(loss)
    train_acc(labels, logits)


@tf.function
def test_step(inputs, labels):
    logits = model(inputs)
    loss = loss_object(labels, logits)
    test_loss(loss)
    test_acc(labels, logits)


for epoch in range(10):
    template = 'Epoch {:>2} Train Loss {:.3f} Test Loss {:.3f} ' \
               'Train Acc {:.2f} Test Acc {:.2f}'

    train_loss.reset_states()
    test_loss.reset_states()
    train_acc.reset_states()
    test_acc.reset_states()

    for X_train, y_train in train_dataset:
        train_step(X_train, y_train)

    for X_test, y_test in test_dataset:
        test_step(X_test, y_test)

    print(template.format(
        epoch + 1,
        train_loss.result(),
        test_loss.result(),
        train_acc.result(),
        test_acc.result()
    ))

【讨论】:

  • 您好 Nico,非常感谢您的回答。我可以再问两个问题吗?在def train_step(inputs, labels) 的定义中,我们有weights=model.trainable_variablesgradients=tape.gradient(loss, weights)。我想新建一个变量weights_right,可以直接写weights_right=weights-(lr+alpha)*gradients吗?我怎样才能用 weights_right 手动前馈 nn?请注意,nn 中的参数仍然是 weights 而不是 weights_right,我只是想使用 weights_right 来计算新的损失。非常感谢您的帮助。
猜你喜欢
  • 2020-06-09
  • 2018-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-11
  • 1970-01-01
  • 2020-05-09
  • 2019-08-08
相关资源
最近更新 更多