Tensorflow实现神经网络
1.TensorFlow的基本介绍:
2.TensorFlow相关函数包的调用
理解点:
(1)math包支持一些数学运算
(2)h5py包支持对一些h5py格式的数据进行读取,本次实验是将手指的数字数据储存为h5py格式文件中。
(3)ops是operations的缩写,指的是TensorFlow中的图节点,相关实例介绍看下图:
(4)tf_utils包是储放了上述函数的一个python文件名,将函数放至改文件中,只要编辑的python文件路径与tf_utils文件路径一致即可直接调用。
3.TensorFlow的简单应用理解:
理解点:
(1)在tensorflow中设置常变量是应用tf.constant(常数值,name = '常数值对应的变量名'),在上例中是将36这一数值存放在y_hat变量中,同理将39这一常量值存放在y变量中。
(2)在TensorFlow中设置变量是应用tf.Variable(变量的数值运算方法,name = '变量名'),在上例中将(y-y_hat)^2的运算数值存放在loss变量中。
(3)tf.global_variables_initializer()是对所有(global)变量进行初始化,如果想有选择性地对变量进行初始化,可以使用tf.initializer_variables([variable1,variable2,variable3...])。
(4)前期的代码可以理解为将变量和运算进行储存,如果要进行运行,必须通过tf.Session(),即可通过sess = tf.Session(),sess.run(所定义的变量名),但是注意如果是用以下代码进行实现,实现完后需要将sess关闭。
sess = tf.Session()
sess.run(variable_i)
sess.close()
另外一种运用with形式,不需要刻意去关闭sess,它在运行完会自动结束这个运行环境,可以类比理解为一个循环结构,如上图例子所示。
4.tensorflow中的tf.placeholder()函数的相关知识点
(1)相关说明:此函数可以理解为形参,用于定义过程,在执行的时候再赋予具体的值
(2)语法结构:tf.placeholder(dtype,shape = None,name)
dtype:数据类型,常用的是tf.float32和tf.float64等数值类型
shape:数据形状,默认是None,即是一维数值,也可是多维,比如[2,3]指的是2行3列,[None,3]指的是3列,行数不确定。
name:名称
(3)应用举例:
理解点:
(1)在上例中的feed_dict是将x进行赋值并代入sess.run()中进行运行,运行结果为6。
(2)在后面需要将sess关闭。
5.tensorflow中实现线性函数
理解点:
(1)此例应用了tensorflow中构造常量的tf.constant()语句,生成了X,W,b三个常值向量。
(2)此例构造的线性函数为Y = WX+b,由此例可以看出在tensorflow中tf.add(a,b)等价于a+b,tf.matmul(W,X)等价于W与X两个矩阵的乘法。
(3)注意上例的result = sess.run(Y)是对Y进行实现,即可得result = WX+b。
6.tensorflow中实现sigmoid()函数
理解点:
(1)此函数首先应用tf.placeholder()函数设置形式参数x
(2)再定义一个sigmoid变量,直接使用tensorflow里的内置函数tf.sigmoid(x)进行计算并定义
(3)利用sess.run(sigmoid,feed_dict = {x:z})将定义的函数中的参数z赋予给x进行sigmoid函数的实现得到result。
7.tensorflow中实现计算神经网络中的损失函数
理解点:
(1)函数首先设置了两个形式参数z和y,指定列额数据类型和名称。
(2)通过tensorflow内置的函数tf.nn.sigmoid_cross_entropy_with_logits()计算损失函数:中的一个值,没有计算平均值。
(3)tf.nn.sigmoid_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, name=None)的介绍:
作用:此函数用于计算经sigmoid()函数**后的交叉熵(corss_entropy)
参数输入说明:
_sentinel:一般情况不太使用的参数,可以保持默认值None
logits:一个tensor,一般是float32或float64数据格式,在损失函数中指的是预测值(y_hat)
labels:一个tensor,数据类型和数据维度和logits一致,在损失函数中指的是真实值(y)
(4)在用sess.run()函数中利用feed_dict = {z:logits,y:labels}将函数的参数(已知量)赋给由tf.placeholder()定义的形参z,y,即将z,y进行了实参话,再回头将实参z,y代入tensorflow中的tf.nn.sigmoid_cross_entropy_with_logits(logits = z,labels = y)中进行损失函数计算。
(5)相关的数学推导过程见链接:https://www.cnblogs.com/cloud-ken/p/7435421.html
(6)该函数的一个测试结果:
8.tensorflow中的One-Hot Encoding处理方法
(1)One-Hot Encoding处理方法介绍:
One-Hot Encoding处理方法可将下图中的y向量进行如下转换:
(2)One-Hot Encoding处理方法的应用:
理解点:
(1)该函数的参数labels是一个数组,形式如上图中的y,C是一个常量
(2)一开始先定义一个常量C。
(3)运用tensorflow中的tf.one_hot()函数结合参数对labels变量进行One-Hot Encoding处理。
(4)对tf.one_hot(indices,depth,on_value = 1,offvalue = 0,axis = 0/1,dtype = None,name = None)函数的相关参数介绍:
indices:函数的输入值,在此要求是一维的,在上例中与labels这一变量对应
depth:one hot的维度,在上例中与C对应,在此depth决定的是行数还是列数由axis决定
当axis = 0时,depth决定的是行数,因axis = 0时代表着one hot是以行形式展开(则需要按列来看结果),得到的结果如下:
当axis = 1时,depth决定的是列数,因axis = 1时代表着one hot是以列形式展开(则需要按行来看结果),得到的结果如下:
(5)通过此函数可以将一个一维向量中的数字信息转换成一个两维向量中的哑变量信息
9.tensorflow中生成零矩阵和ones矩阵
理解点:
(1)函数参数shape决定了矩阵的维度,若shape = [3,2],则生成3行2列元素全是1的矩阵。
(2)tf.ones(shape)函数与np.ones(shape)函数一致,tf.zeros(shape)是生成维度为shape的零矩阵,与np.zeros(())不同的是np.zeros(())是两个小括号。
(3)注意在tensorflow中运用tf.functions()函数生成的变量都需要运用sess.run()进行调用。
10.tensorflow构造神经网络前的准备
前期准备:
(1)问题陈述:通过对图像手指的数量进行识别手指的数字含义。
(2)数据的读取
理解点:
h5py.File('文件路径/文件名.h5',‘r\w’)用来读取hdf5格式的文件数据,并且h5py.File中的数据存储形式类似于python中的字典格式,所以上例在调用train_set_x_orig时直接用的是train_dataset['train_set_x'],与调用字典中的数据方式一致。所以以后要是想调用h5py中的数据时直接调用文件名中的字典键即可调用数据。随后可对数据进行相同的python处理。
(3)数据的可视化
理解点:
(1)了解plt.imshow()的作用:
通过此例可以看出plt.imshow()是将数据变量中的各个数值按照维度位置在图中各相应位置进行标记,例如a向量维度是3行4列,则每一个数据在图中对应着一个块与对应的颜色。
(2)理解plt.imshow(X_train_orig[0])显示出的是一副手画:
X_train_orig.shape = (1080, 64, 64, 3),理解为X_train_orig数据存储了1080张手势图片,而在本例中调用的是一张图片,在X_train_orig[0]中的每一个数据表示的是图中的一个小块(趋近于一个点的大小,即可以理解为像素,也就是说像素是对应的数据点,每个数据点堆积起来便成了手画)。
(3)掌握np.squeeze()作用,比较与np.flatten():
np.squeeze(a)是将所有维度为1的维度去掉,这个操作等价于a.reshape(-1)
np.flatten()将高维数组转化为向量,和reshape不同的是,flatten函数会生成原始数组的复制
(4)数据维度的转换
理解点:
(1)此例第一句代码是将维度情况为(1080,64,64,3)的X_train_orig应用reshape(X_train_orig.shape[0],-1)转换成了维度为(1080,64*64*3)的维度,最后进行转置变成维度为(64*64*3,1080)的X_train_flatten变量,在此处的reshape()语句中,只需要遵循行与X_train_orig.shape[0]一致,列数不管,所以自动转换成了64*64*3列的数据表。此方法可用于将图像数据进行维度转化成神经网络输入层需要的维度数据。
(2)X_train = X_train_flatten/255是对像素数据进行标准化的方法,此方法可以用于图像数据标准化。
(3)将Y的训练数据和测试数据转化成one hot格式的数据,depth=6是因为手指可以比划出0~5的六个数字。
(5)数据存储的设置
理解点:
(1)此函数通过tf.placeholder()为数据集中的自变量X与结果变量Y设置一个存储空间,其中设置数据类型为float32,设置维度时只要求数据的行数要分别等于函数的参数n_x,n_y,在神经网络中n_x指的是输入的变量的个数,在训练集自变量中更多是要求行数要是变量的数量,一般样本的数量(对应于输入矩阵的列数)可不管,训练集的X与Y的样本数量一般是一致的。
(2)此处设置维度情况时[n_x,None]与reshape中的(n_x,-1)是一致的,可以结合起来记忆。
模型构建:
(6)参数的初始化
理解点:
(1)函数首先应用tf.set_random_seed(1)指定随机数生成时只随机生成一次,与np.random_seed(1)的作用一致。
(2)通过tf.get_variable()函数进行变量的设定,并且指定列了变量的键(由引号引出的可以理解为是字典的键),也指定了数据的维度情况。在此函数中的initializer=tf.contrib.layers.xavier_initializer(seed = 1)是生成一个均匀分布的数据,此均匀分布函数为:
此函数中的initializer = tf.zeros_initializer()是生成一个零矩阵数据。
(3)此初始化过程可以拓展记忆为在TensorFlow中生成字典的方法:
键对应的值 = tf.Variable('键名',shape,生成数据的方法(例如生成随机的矩阵或零矩阵等))
(4)个人感觉相比于np中对参数的初始化操作没有特别大的一个区别,都是随机生成一个数,只是np中生成时需要先生成一个空的字典以备存储数据,并且在此处还未体现使用循环语句对各层的参数进行初始化,但原理一致。
np中的循环结构参数初始化:
(7)前向传递结构
(1)此函数与np中的前向传递过程是基本一致的,只是将np中的一些矩阵运算换成了tensorflow中的矩阵运算算法。
(2)此函数与np中的前向传递最大的不同是np中的算法是需要算出输出层的AL,而在tensorflow中只需要并且只允许算出输出层的ZL,原因是在tensorflow中的内置函数算损失函数时是将ZL代入计算的。所以谨记用tensorflow计算前向传递时只能算到ZL即须停止。
(3)注意在tensorflow中计算relu函数的语法是:tf.nn.relu()。
(4)tf.reset_default_graph()是清除默认图的堆栈,并设置全局图为默认图。具体含义还不是很清楚,但在执行with语句之前一定需要先有这个语句。另外还有一个相似语句是tf.get_default_graph()是返回当前线程的默认图。
(5)在此处因没有用到sess.run(),所以with语句可用可不用。在没有sess.run()语句时运行的格式和np中的是一致的,但是在运行的结果不是直接结果的输出,只是输出一个tensor信息,这一点与np中的不一致,因为一般如果想要输出值,需要用sess.run()运行。
(8)计算损失函数
理解点:
(1)此函数计算的损失函数的数学式为:
(2)记忆tf.transpose()函数:此函数是对矩阵进行转置处理的意思,相当于np中的T。
(3)记忆tf.reduce_mean()函数:此函数是对变量进行求均值处理。tensorflow中还有其他数据统计量的相似函数详见链接:http://blog.csdn.net/Hk_john/article/details/78188990?locationNum=6&fps=1
(4)理解并变通掌握tf.nn.softmax_cross_entropy_with_logits(logits = logits,labels = labels)函数:
A.softmax是输出层**函数类型,即上数学式中的sigma,此函数是将输出值分成多类。此时sigma还可为sigmoid、relu等**函数。其中softmax函数的详细介绍见链接:http://m.blog.csdn.net/fengbingchun/article/details/75220591
B.cross_entropy是交叉熵的意思,指的是上述数学式中连加符号里面的式子,交叉熵详细介绍见链接:http://blog.csdn.net/rtygbwwwerr/article/details/50778098
C.logits在这里指的是预测值,labels指的是真实值
D.注意在上数学式中是将ZL代入到输出层的**函数再进行损失函数的求解,这也就解释了为什么在TensorFlow中的前向传递过程中只能计算到ZL而不能计算AL的原因。
(9)模型构建
单句语法理解点:
(1)函数参数的意义:
X_train,Y_train分别是训练数据的自变量和预测变量,用于训练参数
X_test,Y_test分别是测试数据的自变量和预测变量,用于检验参数,在构建模型时可用可不用,也可等后期直接代入训练后的参数中进行检验。
learning_rate是学习率,用于梯度下降法中的参数更新
num_epochs是迭代次数,即训练数据的代入参数模型的次数
minibatch_size是mini-batch中每个组别的样本个数,一般是2的n次方
print_cost是一个控制参数,具体含义还不是很清楚
(2)ops.reset_default_graph()函数是清除默认的堆栈,具体含义不清楚,但一定要在程序之前有此语句才能运行,所以暂时需要记忆。
(3)tf.set_random_seed(1)函数是为了后期进行参数的随机初始化时只生成唯一的随机序列,具体的相关介绍见链接:http://blog.csdn.net/eml_jw/article/details/72353470
(4)X,Y = create_placeholder(n_x,n_y)是将样本的自变量数n_x和因变量Y单变量中的类型数量n_y分别建立一个占位符,以后如果想调用该变量数值直接进行赋值即可。
(5)optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)是tensorflow进行神经网络中的反向传播优化机制,此一句代码等价于np中的所有反向传播和参数优化的函数,甚是强大。此句中的train是因为参数优化是需要训练数据的拟合,AdamOptimizer是指运用了Adam参数优化法(此方法结合了momentum动量法和另外一个优化方法(名字忘记了,只记得原理,详细介绍见前文“梯度下降法优化”),目前是自己掌握的最好的优化方法),此函数的参数是学习率,目的是损失函数最小化,即minimize(cost)。
(6)init = tf.global_Variable_initiallzer()是对全局变量()所有的参数进行初始化,初始化方法由自定义的初始化方法决定。返回一个初始化所有全局变量的操作(Op)。要是你把图“投放进一个”session中后,你就能够通过run 这个操作来初始化所有的全局变量,本质相当于variable_initializers(global_variables())。
(7)minibatches = random_mini_batches(X_train,Y_train,minibatches_size,seed()是将训练集按minibatch_size的规格进行分组,每一组是一个列表,所有组共同组成了一个大的minibatches列表,详细的划分组的代码如下:
(8)_ ,minibatch_cost = sess.run([optimizer, cost], feed_dict={X: minibatch_X, Y: minibatch_Y})是对每一个minibatch中的训练数据进行模型拟合运行,此处同时运行参数优化和损失函数的运算,代入法人值即为minibatch中的自变量与预测变量。在此函数中"_"我的理解是一个占位符,其值一直是None。
(9)epoch_cost += minibatch_cost / num_minibatches放在循环结构中表达的意思是计算的epoch_cost是每个minibatches中的损失函数的平均值。
(10)costs.append(epoch_cost)是每迭代五次记录最后有一次的损失函数数值于列表cost中。
(11)parameters = sess.run(parameters)是将最后迭代生成的参数进行调用更新至新的parameters中,最后此函数返回的变量也是此变量。
(12)correct_prediction = tf.equal(tf.argmax(Z3), tf.argmax(Y))是预测值的输出
tf.argmax(Y):输出列表中最大数对应的索引,默认的axis = 0,详细介绍见链接:http://blog.csdn.net/qq575379110/article/details/70538051
tf.equal(A,B):输出A与B对应索引的值是否相等的布尔值,详细介绍见链接:http://blog.csdn.net/uestc_c2_403/article/details/72232924
此语句的理解:Z3.shape = (n_L,n_L-1),Y.shape = (n_L,m),首先两个tf.argmax()将两个矩阵按每列中的最大值对应的索引找出分别形成两个列表,再看两个列表对应的数值是否相等形成布尔类型列表。此应该根据的是**函数具有单调递增性质,便可通过对比Z_L与Y的列的最大值进行准确性预测。
(13)accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))中的tf.cast()是类型转化函数,将布尔值类型转化成float类型,再进行求平均即求1的频率。tf.cast()详细介绍见链接:http://blog.csdn.net/luoganttcc/article/details/70315538
(14)eval()函数是启动计算的一种方式,详细介绍见链接:https://www.zhihu.com/question/63258737
模型结构理解点:
(1)在tensorflow中参数的初始化,神经网络的前向传递、损失函数的计算和反向传播都需要先进行罗列,但是此罗列与np中不同的是这些都不需要在循环结构中反复调用,只需要在循环结构中调用sess.run()语句,此语句特别需要注意的是除了返回损失函数还有一个空集。
(2)只有在sess.run()环境下,循环结构才能发挥作用,而此循环体就是迭代中使用,另外如果有minbatch,则需要用到循环结构使得每个minibatch中的数据的都能得到sess.run()。