虽然可以通过自己编程实现前向和反向传播过程但是随着神经网络的层数增加会导致编程趋于复杂,为了节省这种工作,可以使用现有深度学习框架。目前的已有的学习框架有很多Tensorflow,caffe,Torch,pytorch,Theano等,使用最多的目前是Tensorflow,本文讲简单介绍下Tensorflow的使用方法。
import tensorflow as tf
sess = tf.InteractiveSession()
第一行代码是导入tensorflow库,一般取别名为tf;第二行是创建一个新的InteractiveSession,使用这个命令会将这个session(会话)注册为默认的session,之后的运算都会在这个session里。
Tensorflow中常量就是定以后值和维度都会变化的量,可以使数字或者数组。如下代码所示a是类型为tf.int16的数值,b是类型为tf.float32的数值,c是大小为4*4的零矩阵,矩阵元素类型为tf.float32
a = tf.constant(4, tf.int16)
b = tf.constant(8, tf.float32)
c = tf.constant(np.zeros(shape=(4,4), dtype=tf.float32))
变量就是数值可以变化的量,如下代码所示,如下代码所示a是类型为tf.int16的数值,b是类型为tf.float32的数值,c是大小为4*4的零矩阵,矩阵元素类型为tf.float32
a = tf.Variable(4, tf.int16)
b = tf.Variable(8, tf.float32)
c = tf.Variable(tf.zeros([4,4]))
TensorFlow用张量这种数据结构来表示所有的数据.你可以把一个张量想象成一个n维的数组或列表.一个张量有一个静态类型和动态类型的维数.张量可以在图中的节点之间流通,上面所说的a,b,c其实都是张量。
Tensorflow的占位符仅仅声明数据位置用于传入数据到计算图,占位符通过会话的feed_dict操作获取数据,形象理解就是一个萝卜一个坑,其中你每个样本的数据是萝卜,占位符就是萝卜坑。下面是占位符定义的例子,其中的None表示不用管行数。
x = tf.placeholder(tf.float32,[None,784])
y = tf.placeholder(tf.float32,[None,10])
神经网络有许多参数,这些参数在训练之前需要初始化,Tensorflow中参数在定义的时候就可以初始化
w = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
其他的参数如迭代次数和学习速率就像python普通定义变量一样
Tensorflow的激活函数使用Tensorflow库提供的激活函数就可以了,以sigmoid函数为例,下面的代码对应着公式
就是前向传播过程中结点的输出,在这个公式定义好后前向和反向内容都会自动实现。
y = tf.nn.sigmoid(tf.matmul(x,W) + b)
Tensorflow也提供了许多损失函数和优化器,举个例子使用交叉熵作为损失函数,梯度下降作为优化算法.第一行中pred为神经网络输出的标签,y为真实标签;第二行learning_rate为学习速率。
loss = tf.reduce_mean(-tf.reduce_sum(pred * tf.log(y), reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
训练过程就是用优化器优化损失函数的过程,需要设置循环来进行迭代,举个例子,第一行是计算预测正确率,第二行是讲预测的正确率转换成tf.float32类型然后求平均,下面的for循环就是训练的主体,每迭代10次输出一次训练的正确率。值得说一下的是第三行代码,这行代码是一次性初始化所有变量;for循环中的第一行就是执行第5节中梯度下降优化算法来训练参数。(当训练数据较大时,会使用batch来进行批量训练)
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(pred, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name='evaluation')
tf.global_variables_initializer().run()
epoch = 100
i = 0
for i in range(epoch):
train_step.run({x: train_x, pred: train_y})
if i % 10 == 0:
train_accuracy = accuracy.eval({x: train_x, pred: train_y})
print("epoch %d, train_accuracy %g" % (i, train_accuracy))
测试就是使用训练好的参数在测试上计算神经网络的输出与真实标签之间的差异,很简单
test_accuracy = accuracy.eval({x:test_x, pred: test_y})
下面是具有两层的神经网络,数据集采用MNIST,给了详细的注释
from tensorflow.example.tutorials.mnist import input_data
import tensorflow as tf
mnist = input_data.read_data_sets("MNIST_data/", one_hot = True) #导入数据,one-hot就是一行只有一个1,其余的全为0
sess.tf.InteractiveSession()
in_units = 784 #输入结点数
h1_units = 256 #隐含层结点数
#第一层的权重和偏置初始化,注意矩阵的维度
w1 = tf.Variable(tf.truncated_normal([in_units,h1_units]), stddev=0.1)
b1 = tf.Variable(tf.zeros([h1_units])
#第二层的权重和偏置初始化,注意矩阵的维度
w2 = tf.Variable(tf.truncated_normal([in_units,10]))
b2 = tf.Variable(tf.zeros([10])
# 占位符,keep-prob是神经网络为了防止过拟合采用dropout方法的概率
x = tf.placeholder(tf.float32,[None,in_units])
y = tf.placeholder(tf.float32,[None,10])
keep_prob = tf.placeholder(tf.float32)
hidden1 = tf.nn.relu(tf.matmul(x, w1) + b1 #第一层网络
hidden1_drop = tf.nn.dropout(hidden1, keep_prob) #dropout
pred = tf.nn.softmax(tf.matmul(hidden_drop, w2) + b2) #网络输出
loss = tf.reduce_mean(-tf.reduce_sum(pred * tf.log(y), reduction_indices=[1])) #损失函数
train_step = tf.train.AdagradOptimizer(0.5).minimize(loss) #优化器,自适应梯度下降,学习速率为0.5
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(pred, 1)) #单个样本是否被正确分类,通过对比sotfmax输出最大的概率与真实标签
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name='evaluation') #计算全部样本的正确率
#开始训练
tf.global_variables_initializer().run()
epoch = 1000 #迭代次数为1000
i = 0
for i in range(epoch):
batch_xs,batch_xs = mnist.train.next_batch(100) #采用mini-batch方法,每次随机抽取大小为100的数据
train_step.run({x: batch_xs, pred: batch_xs, keep_drop = 0.95}) #训练
if i % 100 == 0: #每训练100次输出一次正确率
train_accuracy = accuracy.eval({x: train_x, pred: train_y, keep_drop = 0.95})
print("epoch %d, train_accuracy %g" % (i, train_accuracy))
#测试,输出模型在测试集上的正确率,测试时keep_drop要为1
print(accuracy.eval({x: mnist.test.images, pred: mnist.test.labels, keep_drop = 1.0}))