使⽤TensorFlow实现DNN
这⼀节使⽤TF实现⼀个多层神经⽹络模型来对MNIST数据集进⾏分类,这⾥我们设计⼀个含有两个隐藏层的神经⽹络,在输出部分使⽤softmax对结果进⾏预测。
使⽤⾼级API实现多层神经⽹络###
这⾥我们使⽤ib包,这是⼀个⾼度封装的包,⾥⾯包含了许多类似seq2seq、keras⼀些实⽤的⽅法。
先引⼊数据
ist import input_data
mnist = ad_data_sets("./") #⾃动下载数据到这个⽬录
X_train = ain.images
X_test = st.images
y_train = ain.labels.astype("int")
y_test = st.labels.astype("int")
>>X_train
array([[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
...,
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.]], dtype=float32)
>>len(X_train)
55000
>>len(X_train[0])
784
>>X_train[0]
array([ 0., 0., 0., ..., 0., 0., 0.], dtype=float32)
>>y_test
array([7, 2, 1, ..., 4, 5, 6])
模型的主要代码
features_cols = tf.contrib.learn.infer_real_valued_columns_from_input(X_train)
dnn_clf = tf.contrib.learn.DNNClassifier(hidden_units=[300,100], n_classes=10, feature_columns=features_cols)
dnn_clf.fit(X_train, y_train, batch_size=50, steps=10000)
ics import accuracy_score
y_pred = dnn_clf.predict(X_test)
print(accuracy_score(y_test, list(y_pred)))
其中infer_real_valued_columns_from_input这个⽅法根据名字可以看出,它是根据输⼊的数据来推算出数据的类型,该例⼦中features_cols 的值为[_RealValuedColumn(column_name='', dimension=784, default_value=None, dtype=tf.float32, normalizer=None)],短短⼏⾏代码就实现了⼀个多层神经⽹络模
型。并且可能会发现上⾯这些与有些不同,不需要对变量进⾏初始化,不需要创建session,使⽤起来⼗分的简单。
使⽤TF实现多层神经⽹络###
⾼度封装的API调⽤起来固然很爽,但是⾃⼰不了解内部的原理使⽤起来就不是那么的踏实,下⾯就使⽤TF实现同样的模型,代码主要分为两部分,构建TF计算流图和执⾏计算图。希望读者能够对⽐上⾯的代码来看接下来的部分。
tensorflow版本选择构建TF计算流图####
⾸先我们需要根据输⼊的数据来设定输⼊的参数,使⽤的数据集MNIST为28*28的矩阵,整个神经⽹络包含两个隐藏层
n_inputs = 28 * 28
n_hidden1 = 300
n_hidden2 = 100
n_output = 10
X = tf.placeholder(tf.float32,shape=(None,n_inputs),name='X')
y = tf.placeholder(tf.int64,shape=(None),name='y')#注意数据类型
上⾯使⽤占位符的⽅法来声明模型的输⼊X和y,需要注意的是占位符的数据类型,在执⾏阶段,占位符会被输⼊的数据所替代。接下来我们需要创建模型的两个隐藏层和输出层,两个隐藏使⽤Relu作为激活函数,输出层使⽤softmax。每⼀层需要指定节点的个数。
def neuron_layer(X,n_neurons,name,activation=None):
with tf.name_scope(name):
n_inputs = _shape()[1]) #特征个数
stddev = 2 / np.sqrt(n_inputs)
init = tf.truncated_normal((n_inputs,n_neurons),stddev=stddev)
W = tf.Variable(init,name='weight')
b = tf.s([n_neurons]),name='baise')
z = tf.matmul(X,W) + b
if activation == "relu":
lu(z)
else:
return z
我将逐⾏的对上⾯代码进⾏解释:
1.为了⽅便在TensorBoard上⾯查看,每⼀层的神经⽹络都创建⼀个name_scope。这⼀步是可选操作,如果不需要在TensorBoard查看
那就可以忽略掉。
2.根据输⼊的数据的形状来获取数据的特征个数(第⼆个维度)
3.接下来的代码是创建权重矩阵W和偏置b,权重W不能使⽤0进⾏初始化,这样会导致所有的神经元的输出为0,出现对称失效问题,
这⾥使⽤truncated normal分布(Gaussian)来初始化权重,
通过指定均值和标准⽅差来⽣成正态分布,抛弃那些⼤于2倍stddev的值。这样将有助于加快训练速度。在初始化b的时候,每⼀层只有⼀个偏置,我们全部设置为0,这样并不会出现对称失效问题。
4.下⾯的是在每⼀个神经元中的操作\(y=X·W+b\),使⽤向量化运算计算输⼊与权重的和运算
5.最后就是激活函数的选择了
下⾯我们就开始像搭建积⽊⼀样创建我们的神经⽹络了,每⼀层的输⼊为上⼀层的输出:
with tf.name_scope("dnn"):
hidden1 = neuron_layer(X,n_hidden1,"hidden1",activation="relu")
hidden2 = neuron_layer(hidden1,n_hidden2,"hidden2",activation="relu")
logits = neuron_layer(hidden2,n_output,"output")
上⾯这⼀段代码的输出层并没有经过softmax激活函数,这是考虑到后续优化求解原因,在后续⼯作中单独做处理。上⾯这段代码就是⼀个神经⽹络全连接的简化版本,当然TF的contrib模块也提供了全连接的函数fully_connected。
ib.layers import fully_connected
with tf.name_scope("dnn"):
hidden1 = fully_connected(X, n_hidden1, scope="hidden1")#激活函数默认为relu
hidden2 = fully_connected(hidden1, n_hidden2, scope="hidden2")
logits = fully_connected(hidden2, n_outputs, scope="outputs",activation_fn=None)
现在,模型已经有了。接下来套路就是设计损失函数,优化损失函数求解参数。输出层softmax输出的
为在各个类别上⾯的得分,损失函数使⽤交叉熵
\(-\sum{y'}log(y')\)。在这⾥我们使⽤TF提供的tf.nn.sparse_softmax_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, name=None)来计算损失函数,该⽅法先计算softmax再计算cross entropy,主要有两个参数需要考虑
1.labels:输⼊的为标签的index,例如本例⼦有10个类别,取值范围为0-9
2.logits:为输⼊到softmax激活函数之前的模型的输出
最后再使⽤reduce_mean()计算loss。
with tf.name_scope("loss"):
xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y,logits=logits)#labels允许的数据类型有int32, int64
loss = tf.reduce_mean(xentropy,name="loss")
note:TF还提供了softmax_cross_entropy_with_logits(),和上⾯⽅法的区别该⽅法输⼊的label为⼀个one-hot向量。
到这⾥我们的模型和损失函数已经都有了,就到了优化阶段,本⽂使⽤梯度下降⽅法
learning_rate = 0.01
with tf.name_scope("train"):
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
training_op = optimizer.minimize(loss)
模型有了结果,就需要对得到的模型进⾏衡量。简单起见,这⾥使⽤accuracy作为评估指标,判断模型输出结果的最⾼值的index是否和label 的index相等
with tf.name_scope("eval"):
correct = tf.nn.in_top_k(logits,y,1) #取值最⾼的⼀位
accuracy = tf.reduce_mean(tf.cast(correct,tf.float32)) #结果boolean转为0,1
模型构建阶段最后⼀个⼯作就是初始化⾥⾯的变量
init = tf.global_variables_initializer()
saver = tf.train.Saver()
执⾏计算流图####
这⼀部分相对前⾯⼯作要简单很多,
n_epoch = 400
batch_size = 50
with tf.Session() as sess:
init.run()
for epoch in range(n_epoch):
for iteration in ain.num_examples // batch_size):#需要迭代的轮数
X_batch,y_batch = _batch(batch_size)
sess.run(training_op,feed_dict={X:X_batch,y:y_batch})
acc_train = accuracy.eval(feed_dict={X:X_batch,y:y_batch})
acc_test = accuracy.eval(feed_dict={st.st.labels})
print (epoch,"Train accuracy", acc_train,"Test accuracy",acc_test)
saver.save(sess, "./my_model.pk")
上⾯这段代码使⽤的是mini-batch⽅法训练神经⽹络,最后将模型持久化到本地。后续的使⽤
with tf.Session() as sess:
X_new_scaled = st.images[:20]
Z = logits.eval(feed_dict={X: X_new_scaled}) #模型
y_pred = np.argmax(Z, axis=1)
总结###
本⽂介绍了TF在实际数据集MNIST上⾯的使⽤,为input和target创建占位符,创建神经⽹络的layer,得到⼀个DNN,并为整个模型设置损失函数,对损失函数进⾏优化求解,最后对模型进⾏评估。
⼜是⼀个凌晨12点,晚安~
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论