如何在 fit/partial_fit 之后操纵 skflow 模型的权重?
How to manipulate weights of an skflow model after fit/partial_fit?
我正在基于 Tensorflow 的 skflow 库构建多个 DNN 模型。我将我的数据分成小批量并使用 partial_fit 进行拟合。在 partial_fit 的每个循环之后,我想将 TensorFlowDNNClassifier 模型的前 n 个隐藏层的权重复制到另一个 TensorFlowDNNClassifier 模型。然后使用 partial_fit 继续 learning/copying。 (两个模型的前 n 个隐藏层的拓扑结构相同。)
我知道如何从 classifier1:
中检索权重
classifier.get_tensor_value('dnn/layer0/Linear/Matrix:0')
但我不知道如何将它们的值复制到 classifier2!
用例:
我正在尝试基于 skflow 的 TensorFlowDNNClassifier/TensorFlowDNNRegressor 构建 M DNN 模型的集合。我希望这些 M 模型彼此共享前 n 层。也就是说,相同的输入、架构和 值 。我想在对 skflow 的原始代码进行最小更改的情况下完成此操作。为此,我考虑将我的数据分成小批量,然后一次训练一个小批量的模型。在每个步骤中(使用小批量),我在一个模型上应用 partial_fit 并将其第一个 n 隐藏层的权重复制到集成中的下一个模型。然后我 partial_fit 第二个模型使用相同的小批量,然后我将权重的新值复制到下一个模型。我重复这个 training/copying 直到我到达合奏中的最后一个模型。在训练完第 M 个模型后,我将其前 n 个隐藏层的权重复制到之前的所有 (M-1) 个模型中。然后我对下一个小批量重复此操作,直到所有 M 个模型的权重收敛。
编辑:感谢@Ismael 和@ilblackdragon(来自另一个论坛)提供的宝贵意见。他们建议的解决方案在创建模型时效果最好。我必须向 TensorFlowEstimator 添加额外的功能,以便我可以在训练时轻松地将权重从一个模型复制到另一个模型(对小批量进行多步训练)。我将以下函数添加到 class TensorFlowEstimator(在文件 estimators/base.py 中定义)
def extract_num_hidden_layers(self,graph_ops):
nhl = 0
are_there_more_layers = True
while are_there_more_layers:
are_there_more_layers = False
layerName = 'dnn/layer' + str(nhl) + '/Linear/Matrix'
for op in graph_ops:
if(op.name == layerName):
nhl+=1
are_there_more_layers = True
break
return nhl
def create_updaters(self):
self.weight_updaters = []
self.bias_updaters = []
for h in range(0,self.num_hidden_layers):
with tf.variable_scope('', reuse=True):
wName = 'dnn/layer' + str(h) + '/Linear/Matrix'
wUpOp = tf.assign(tf.get_variable(wName), self.nValues)
self.weight_updaters.append(wUpOp)
bName = 'dnn/layer' + str(h) + '/Linear/Bias'
bUpOp = tf.assign(tf.get_variable(bName), self.nValues)
self.bias_updaters.append(bUpOp)
def get_layer_weights(self, layer_num):
layer_name = 'dnn/layer' + str(layer_num) + '/Linear/Matrix:0'
return self.get_tensor_value(layer_name)
def get_layer_biases(self, layer_num):
layer_name = 'dnn/layer' + str(layer_num) + '/Linear/Bias:0'
return self.get_tensor_value(layer_name)
def get_layer_params(self, layer_num):
return [self.get_layer_weights(layer_num), self.get_layer_biases(layer_num)]
def set_layer_weights(self, layer_num, weights_values):
self._session.run(self.weight_updaters[layer_num],
feed_dict = {self.nValues: weights_values})
def set_layer_biases(self, layer_num, biases_values):
self._session.run(self.bias_updaters[layer_num],
feed_dict = {self.nValues: biases_values})
def set_layer_params(self, layer_num, params_values):
self.set_layer_weights(layer_num, params_values[0])
self.set_layer_biases(layer_num, params_values[1])
在使用 self.model_fn(self._inp, self._out)
graph_ops = self._graph.get_operations()
self.num_hidden_layers = self.extract_num_hidden_layers(graph_ops)
self.nValues = tf.placeholder(tf.float32)
#self.weight_updaters & self.bias_updaters
self.create_updaters()
以及如何使用 getter 和 setter 函数:
iris = datasets.load_iris()
classifier = skflow.TensorFlowDNNClassifier(hidden_units=[10,5,4], n_classes=3,continue_training=True)
classifier.fit(iris.data, iris.target)
l1b = classifier.get_layer_biases(1)
l1b[3] = 2 # here I manually change the value for demo
classifier.set_layer_biases(1,l1b)
您应该使用 TensorFlowEstimator,您可以在其中定义您的自定义模型,基本上您可以将任何 TensorFlow 代码插入到自定义模型中。
因此,如果您知道如何检索权重,则可以使用 tf.Variable 并将权重作为初始值传递给新的 dnn,因为:
tf.Variable could have a Tensor or Python object convertible to a
Tensor as initial value
。所以我认为权重的转移应该是这样的:
weights_i = classifier_i.get_tensor_value('dnn/layer0/Linear/Matrix:0')
def my_model_i_plus_1(X, y):
W = tf.Variable(weights_i)
b = tf.Variable(tf.zeros([biases_size]))
layer = tf.nn.relu(tf.matmul(X, W) + b)
return skflow.models.logistic_regression(layer, y)
classifier_i_plus_1 = skflow.TensorFlowEstimator(model_fn=my_model_i_plus_1,
n_classes=3,
optimizer="SGD")
我正在基于 Tensorflow 的 skflow 库构建多个 DNN 模型。我将我的数据分成小批量并使用 partial_fit 进行拟合。在 partial_fit 的每个循环之后,我想将 TensorFlowDNNClassifier 模型的前 n 个隐藏层的权重复制到另一个 TensorFlowDNNClassifier 模型。然后使用 partial_fit 继续 learning/copying。 (两个模型的前 n 个隐藏层的拓扑结构相同。)
我知道如何从 classifier1:
中检索权重classifier.get_tensor_value('dnn/layer0/Linear/Matrix:0')
但我不知道如何将它们的值复制到 classifier2!
用例:
我正在尝试基于 skflow 的 TensorFlowDNNClassifier/TensorFlowDNNRegressor 构建 M DNN 模型的集合。我希望这些 M 模型彼此共享前 n 层。也就是说,相同的输入、架构和 值 。我想在对 skflow 的原始代码进行最小更改的情况下完成此操作。为此,我考虑将我的数据分成小批量,然后一次训练一个小批量的模型。在每个步骤中(使用小批量),我在一个模型上应用 partial_fit 并将其第一个 n 隐藏层的权重复制到集成中的下一个模型。然后我 partial_fit 第二个模型使用相同的小批量,然后我将权重的新值复制到下一个模型。我重复这个 training/copying 直到我到达合奏中的最后一个模型。在训练完第 M 个模型后,我将其前 n 个隐藏层的权重复制到之前的所有 (M-1) 个模型中。然后我对下一个小批量重复此操作,直到所有 M 个模型的权重收敛。
编辑:感谢@Ismael 和@ilblackdragon(来自另一个论坛)提供的宝贵意见。他们建议的解决方案在创建模型时效果最好。我必须向 TensorFlowEstimator 添加额外的功能,以便我可以在训练时轻松地将权重从一个模型复制到另一个模型(对小批量进行多步训练)。我将以下函数添加到 class TensorFlowEstimator(在文件 estimators/base.py 中定义)
def extract_num_hidden_layers(self,graph_ops):
nhl = 0
are_there_more_layers = True
while are_there_more_layers:
are_there_more_layers = False
layerName = 'dnn/layer' + str(nhl) + '/Linear/Matrix'
for op in graph_ops:
if(op.name == layerName):
nhl+=1
are_there_more_layers = True
break
return nhl
def create_updaters(self):
self.weight_updaters = []
self.bias_updaters = []
for h in range(0,self.num_hidden_layers):
with tf.variable_scope('', reuse=True):
wName = 'dnn/layer' + str(h) + '/Linear/Matrix'
wUpOp = tf.assign(tf.get_variable(wName), self.nValues)
self.weight_updaters.append(wUpOp)
bName = 'dnn/layer' + str(h) + '/Linear/Bias'
bUpOp = tf.assign(tf.get_variable(bName), self.nValues)
self.bias_updaters.append(bUpOp)
def get_layer_weights(self, layer_num):
layer_name = 'dnn/layer' + str(layer_num) + '/Linear/Matrix:0'
return self.get_tensor_value(layer_name)
def get_layer_biases(self, layer_num):
layer_name = 'dnn/layer' + str(layer_num) + '/Linear/Bias:0'
return self.get_tensor_value(layer_name)
def get_layer_params(self, layer_num):
return [self.get_layer_weights(layer_num), self.get_layer_biases(layer_num)]
def set_layer_weights(self, layer_num, weights_values):
self._session.run(self.weight_updaters[layer_num],
feed_dict = {self.nValues: weights_values})
def set_layer_biases(self, layer_num, biases_values):
self._session.run(self.bias_updaters[layer_num],
feed_dict = {self.nValues: biases_values})
def set_layer_params(self, layer_num, params_values):
self.set_layer_weights(layer_num, params_values[0])
self.set_layer_biases(layer_num, params_values[1])
在使用 self.model_fn(self._inp, self._out)
graph_ops = self._graph.get_operations()
self.num_hidden_layers = self.extract_num_hidden_layers(graph_ops)
self.nValues = tf.placeholder(tf.float32)
#self.weight_updaters & self.bias_updaters
self.create_updaters()
以及如何使用 getter 和 setter 函数:
iris = datasets.load_iris()
classifier = skflow.TensorFlowDNNClassifier(hidden_units=[10,5,4], n_classes=3,continue_training=True)
classifier.fit(iris.data, iris.target)
l1b = classifier.get_layer_biases(1)
l1b[3] = 2 # here I manually change the value for demo
classifier.set_layer_biases(1,l1b)
您应该使用 TensorFlowEstimator,您可以在其中定义您的自定义模型,基本上您可以将任何 TensorFlow 代码插入到自定义模型中。
因此,如果您知道如何检索权重,则可以使用 tf.Variable 并将权重作为初始值传递给新的 dnn,因为:
tf.Variable could have a Tensor or Python object convertible to a Tensor as initial value
。所以我认为权重的转移应该是这样的:
weights_i = classifier_i.get_tensor_value('dnn/layer0/Linear/Matrix:0')
def my_model_i_plus_1(X, y):
W = tf.Variable(weights_i)
b = tf.Variable(tf.zeros([biases_size]))
layer = tf.nn.relu(tf.matmul(X, W) + b)
return skflow.models.logistic_regression(layer, y)
classifier_i_plus_1 = skflow.TensorFlowEstimator(model_fn=my_model_i_plus_1,
n_classes=3,
optimizer="SGD")