在TensorFlow中设计一个代表网络的类

时间:2018-07-10 02:15:36

标签: python tensorflow

我正在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)

我认为这种组织事情的方式是有缺陷的,因为:

  • 假设我训练了我的网络参数,然后想用这些参数进行预测。我必须在同一TensorFlow会话中执行此操作,否则所有内容都会被清除掉,而我将重新开始。 (问题: 该陈述正确吗?

如果这是正确的,则在两个方法之间拆分这些函数似乎没有意义,因为会话将在它们之间关闭。

作为参考,我正在尝试使用此类的东西类似于以下脚本。它以恒定函数训练网络,然后将其第一个预测与训练后的预测进行比较。

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)))

但是它在训练前后吐出了同样的东西。

问题:组织这些事情的通常更聪明的方法是什么?我对每个网络体系结构都有不同的类的想法:我是否需要完全放弃该想法?还是只是以一种更聪明的方式编写方法?

1 个答案:

答案 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()来评估您的操作。

另一种选择是,您可以在一个会话中训练模型,将其保存到磁盘,然后在另一个会话中将其还原以进行推理。这回答了您的第一个问题,因为不同的会话确实会清除信息,但可以将其存储在磁盘上(考虑到您不想每次进行一次推理之前都进行训练,这很有意义)。