我正在TensorFlow中进行一些数值实验,其中涉及创建一些简单的网络,并观察它们可以近似地逼近各种功能。
我的第一个想法是为要比较的每种网络类型创建一个不同的Python类。但是我认为我编写课程的方式是有缺陷的。例如,我的第一个叫AffineNetwork
。它具有用于训练网络的方法和用于通过网络简单地输入输入的方法。
import numpy as np
import tensorflow as tf
class AffineNetwork:
def __init__(self, trainingData, targets, initialParams):
self.trainingData = trainingData
self.targets = targets
self.weights = tf.get_variable("weights", initializer = tf.constant(initialParams[0]))
self.bias = tf.get_variable("bias", initializer = tf.constant(initialParams[1]))
self.outputs = tf.expand_dims(self.weights,0) @ trainingData + self.bias
self.loss = tf.reduce_mean(tf.square(self.targets - self.outputs))
self.optimizer = tf.train.GradientDescentOptimizer(0.001)
self.train_step = self.optimizer.minimize(self.loss)
self.init = tf.global_variables_initializer()
self.loss_summary = tf.summary.scalar("loss", self.loss)
def train(self, max_iter, directory_name):
with tf.Session() as sess:
sess.run(self.init)
writer = tf.summary.FileWriter("Tensorboard/" + directory_name)
for step in range(max_iter):
sess.run(self.train_step)
summ = sess.run(self.loss_summary)
writer.add_summary(summ, step)
writer.close()
def feedforward(self, x):
if len(x.shape) == 1:
x = tf.expand_dims(x, 1)
with tf.Session() as sess:
sess.run(self.init)
return sess.run(tf.expand_dims(self.weights,0) @ x + self.bias)
我认为这种组织事情的方式是有缺陷的,因为:
如果这是正确的,则在两个方法之间拆分这些函数似乎没有意义,因为会话将在它们之间关闭。
作为参考,我正在尝试使用此类的东西类似于以下脚本。它以恒定函数训练网络,然后将其第一个预测与训练后的预测进行比较。
dim = 3
dataSetSize = 5
trainingData = np.array(np.arange(15).astype(np.float32).reshape(dim, dataSetSize))
targets = np.ones(dataSetSize, dtype = np.float32)
initialParams = [np.random.uniform(0.0, 1.0, dim).astype(np.float32), np.float32(0)]
myAffineNetwork = nt.AffineNetwork(trainingData, targets,initialParams)
print(myAffineNetwork.feedforward(np.array([1, 2, 3], dtype=np.float32)))
myAffineNetwork.train(50, output_folder_name)
print(myAffineNetwork.feedforward(np.array([1, 2, 3], dtype=np.float32)))
但是它在训练前后吐出了同样的东西。
问题:组织这些事情的通常更聪明的方法是什么?我对每个网络体系结构都有不同的类的想法:我是否需要完全放弃该想法?还是只是以一种更聪明的方式编写方法?
答案 0 :(得分:1)
为网络定义类并不是一个坏主意。 Danijar(LINK)指出TensorFlow代码库中的所有模型都是以这种方式定义的。
要解决您的问题,您可以做几件事。首先,当您定义__init__()
方法时,您可以为该对象定义一个会话:
class AffineNetwork:
def __init__(self, trainingData, targets, initialParams):
self.trainingData = trainingData
self.targets = targets
self.weights = tf.get_variable("weights", initializer = tf.constant(initialParams[0]))
self.bias = tf.get_variable("bias", initializer = tf.constant(initialParams[1]))
self.outputs = tf.expand_dims(self.weights,0) @ trainingData + self.bias
self.loss = tf.reduce_mean(tf.square(self.targets - self.outputs))
self.optimizer = tf.train.GradientDescentOptimizer(0.001)
self.train_step = self.optimizer.minimize(self.loss)
self.init = tf.global_variables_initializer()
self.loss_summary = tf.summary.scalar("loss", self.loss)
self.sess = tf.Session()
这样,您就可以对所有操作使用相同的会话。不过,您必须修改其余的代码,例如使用self.sess.run()
来评估您的操作。
另一种选择是,您可以在一个会话中训练模型,将其保存到磁盘,然后在另一个会话中将其还原以进行推理。这回答了您的第一个问题,因为不同的会话确实会清除信息,但可以将其存储在磁盘上(考虑到您不想每次进行一次推理之前都进行训练,这很有意义)。