我在玩Udacity深度学习课程中的一个ANN(人工神经网络)。
我的作业需要在包含一个隐藏ReLU层的网络中引入泛化,使用L2损失。我想知道如何正确引入它,以便所有权重都被惩罚,而不仅仅是输出层的权重。
没有泛化的网络代码在帖子的底部(运行训练的代码不在问题的范围内)。
引入L2损失的一个明显方法是用类似这样的代码替换损失计算(如果beta是0.01):
loss = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits(out_layer, tf_train_labels) + 0.01*tf.nn.l2_loss(out_weights))
但在这种情况下,它只会考虑输出层权重的值。我不确定如何正确地惩罚进入隐藏ReLU层的权重。这是否真的需要,或者引入输出层的惩罚是否也能某种程度上控制隐藏层的权重?
#一些导入from __future__ import print_functionimport numpy as npimport tensorflow as tffrom six.moves import cPickle as picklefrom six.moves import range#加载数据pickle_file = '/home/maxkhk/Documents/Udacity/DeepLearningCourse/SourceCode/tensorflow/examples/udacity/notMNIST.pickle'with open(pickle_file, 'rb') as f: save = pickle.load(f) train_dataset = save['train_dataset'] train_labels = save['train_labels'] valid_dataset = save['valid_dataset'] valid_labels = save['valid_labels'] test_dataset = save['test_dataset'] test_labels = save['test_labels'] del save # 提示帮助gc释放内存 print('训练集', train_dataset.shape, train_labels.shape) print('验证集', valid_dataset.shape, valid_labels.shape) print('测试集', test_dataset.shape, test_labels.shape)#准备数据以适应tensorflow的正确格式#即数据是扁平矩阵,标签是一热编码image_size = 28num_labels = 10def reformat(dataset, labels): dataset = dataset.reshape((-1, image_size * image_size)).astype(np.float32) # 将0映射到[1.0, 0.0, 0.0 ...],1映射到[0.0, 1.0, 0.0 ...] labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32) return dataset, labelstrain_dataset, train_labels = reformat(train_dataset, train_labels)valid_dataset, valid_labels = reformat(valid_dataset, valid_labels)test_dataset, test_labels = reformat(test_dataset, test_labels)print('训练集', train_dataset.shape, train_labels.shape)print('验证集', valid_dataset.shape, valid_labels.shape)print('测试集', test_dataset.shape, test_labels.shape)#现在是有趣的部分 - 我们要构建一个网络,包含#一个隐藏的ReLU层和我们常用的输出线性层#我们将使用SGD,所以这是我们的批量大小batch_size = 128#构建tensorflow图graph = tf.Graph()with graph.as_default(): # 输入数据。对于训练数据,我们使用一个占位符,在运行时将用训练小批量数据填充 # at run time with a training minibatch. tf_train_dataset = tf.placeholder(tf.float32, shape=(batch_size, image_size * image_size)) tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels)) tf_valid_dataset = tf.constant(valid_dataset) tf_test_dataset = tf.constant(test_dataset) #现在让我们构建我们的新隐藏层 #这是我们想要的隐藏神经元数量 num_hidden_neurons = 1024 #它的权重 hidden_weights = tf.Variable( tf.truncated_normal([image_size * image_size, num_hidden_neurons])) hidden_biases = tf.Variable(tf.zeros([num_hidden_neurons])) #现在是层本身。它将数据乘以权重,加上偏置 #并对结果取ReLU hidden_layer = tf.nn.relu(tf.matmul(tf_train_dataset, hidden_weights) + hidden_biases) #现在是输出线性层的时间 #输出权重连接隐藏神经元到输出标签 #偏置被添加到输出标签 out_weights = tf.Variable( tf.truncated_normal([num_hidden_neurons, num_labels])) out_biases = tf.Variable(tf.zeros([num_labels])) #计算输出 out_layer = tf.matmul(hidden_layer,out_weights) + out_biases #我们的真实输出是先前结果的softmax #我们还计算其交叉熵以获得我们的损失 loss = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits(out_layer, tf_train_labels)) #现在我们只需最小化这个损失来实际训练网络 optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss) #很好,现在让我们计算每个数据集上的预测,以评估 #迄今为止的性能 # 对训练、验证和测试数据的预测。 train_prediction = tf.nn.softmax(out_layer) valid_relu = tf.nn.relu( tf.matmul(tf_valid_dataset, hidden_weights) + hidden_biases) valid_prediction = tf.nn.softmax( tf.matmul(valid_relu, out_weights) + out_biases) test_relu = tf.nn.relu( tf.matmul( tf_test_dataset, hidden_weights) + hidden_biases) test_prediction = tf.nn.softmax(tf.matmul(test_relu, out_weights) + out_biases)
回答:
hidden_weights
, hidden_biases
, out_weights
, 和 out_biases
都是你创建的模型参数。你可以像下面这样对所有这些参数添加L2正则化:
loss = (tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits( logits=out_layer, labels=tf_train_labels)) + 0.01*tf.nn.l2_loss(hidden_weights) + 0.01*tf.nn.l2_loss(hidden_biases) + 0.01*tf.nn.l2_loss(out_weights) + 0.01*tf.nn.l2_loss(out_biases))
根据@【隐藏人名】的建议,不对偏置进行正则化:
loss = (tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits( logits=out_layer, labels=tf_train_labels)) + 0.01*tf.nn.l2_loss(hidden_weights) + 0.01*tf.nn.l2_loss(out_weights) +