#主要根据一个神经网络来讲解基础的tensorflow的应用。在实现一个神经网络的过程,来讲解tensorflow的应用。具体讲了每个函数的作用和意义。 #还有就是讲解了dropout的作用,非线性激励函数,损失函数,还有优化算法。 # Parameters,开始的时候,这个设施大一点,然后慢慢的修改 learning_rate = 0.001 #训练的循环次数,用来提高准确率,降低错误率.也是更新w和b.在这里,由于数据小,这个一次epoch会循环一次数据 #在训练中,我们在每个 epoch 送入单个数据点。这被称为随机梯度下降(stochastic gradient descent)。随机梯度下降 # 我们也可以在每个 epoch 送入一堆数据点,这被称为 mini-batch 梯度下降(这里采用的是mini-batch), # 或者甚至在一个 epoch 一次性送入所有的数据点,这被称为 batch 梯度下降。batch梯度下降 training_epochs = 30 #设置每次输入数据的大小 batch_size = 100 #无关,主要是显示作用 display_step = 5 # Network Parameters,有784 神经元输入(输入数据的维数),第一个隐藏层有256个神经元,第二个隐藏层有512个神经元,10个神经元输出(label 个数) n_hidden_1 = 256 # 1st layer number of features第一隐藏层 n_hidden_2 = 512 # 2nd layer number of features第二隐藏层 n_input = 784 # MNIST data input (img shape: 28*28)输入层 n_classes = 10 # MNIST total classes (0-9 digits)输出层 # tf Graph input 占位符 x = tf.placeholder("float", [None, n_input]) y = tf.placeholder("float", [None, n_classes]) # Create model,建造二神经网络包括两个隐藏层 def multilayer_perceptron(x, weights, biases): # Hidden layer with RELU activation layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1']) #这里采用非线性激励函数,是解决非线性数据问题.对于非线性激励函数,四种选择(可能更多) #1 sigmoid
#2 tahn
#3 ReLU(常用,因为特征度足够多,可以损失一些函数)
#4 Leaky ReLU
#非线性激励函数:正向截断负值,损失大量特征 layer_1 = tf.nn.relu(layer_1) # Hidden layer with RELU activation layer_2 = tf.add(tf.matmul(layer_1, weights['h2']), biases['b2']) #非线性激励函数:正向截断负值,损失大量特征 layer_2 = tf.nn.relu(layer_2) # we can add dropout layer参数太多,有时候随机设为0,维数变.用剩余的参数进行计算。 # overfitting的表现形式:可能就是一些weight特别的大,然后其他一些weight特别的小或者为0。 # 想要的的参数尽量均衡,让来的数据都有贡献.随机设为0。当随机设为0的之后,若预测结果并没有太大的改变,说明weight较为均衡。 drop_out = tf.nn.dropout(layer_2, 0.75) # Output layer with linear activation输出层,只是线性的输出 out_layer = tf.matmul(layer_2, weights['out']) + biases['out'] return out_layer # Store layers weight & biases 设置权重和斜偏率. # 对于weight函数,这里设置为随机的,因为如果weight设置为相等的,这回造成所有的输入数据就有类似的效果. weights = { 'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])), 'h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])), 'out': tf.Variable(tf.random_normal([n_hidden_2, n_classes])) } biases = { 'b1': tf.Variable(tf.random_normal([n_hidden_1])), 'b2': tf.Variable(tf.random_normal([n_hidden_2])), 'out': tf.Variable(tf.random_normal([n_classes])) } # 让模型训练做分类 pred = multilayer_perceptron(x, weights, biases) # Define loss and optimizer loggits为预测的结果,labels为实际label cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
#扩展:TensorFlow四种Cross Entropy算法实现和应用 #交叉熵介绍(文献2) #交叉熵(Cross Entropy)是Loss函数的一种(也称为损失函数或代价函数),用于描述模型预测值与真实值的差距大小, # 常见的Loss函数就是均方平方差(Mean Squared Error)平方差很好理解,预测值与真实值直接相减, # 为了避免得到负数取绝对值或者平方,再做平均就是均方平方差。注意这里预测值需要经过sigmoid激活函数,得到取值范围在0到1之间的预测值。 # 平方差可以表达预测值与真实值的差异,但在分类问题种效果并不如交叉熵好. #首先是交叉熵得到的值一定是正数,其次是预测结果越准确值越小,注意这里用于计算的“a” 也是经过sigmoid激活的,取值范围在0到1。 #如果label是1,预测值也是1的话,前面一项y * ln(a)就是1 * ln(1)等于0,后一项(1 - y) * ln(1 - a)也就是0 * ln(0)等于0,Loss函数为0, #反之Loss函数为无限大非常符合我们对Loss函数的定义。这里多次强调sigmoid激活函数,是因为在多目标或者多分类的问题下有些函数是不可用的, #而TensorFlow本身也提供了多种交叉熵算法的实现。 #tf.nn.sigmoid_cross_entropy_with_logits # sigmoid_cross_entropy_with_logits,因为它的实现和前面的交叉熵算法定义是一样的 # 输入是logits和targets,logits就是神经网络模型中的 W * X矩阵,注意不需要经过sigmoid,而targets的shape和logits相同, # 就是正确的label值,例如这个模型一次要判断100张图是否包含10种动物,这两个输入的shape都是[100, 10]。 # 注释中还提到这10个分类之间是独立的、不要求是互斥,这种问题我们成为多目标,例如判断图片中是否包含10种动物,label值可以包含多个1或0个1, #tf.nn.softmax_cross_entropy_with_logits #上面的函数不能解决多分类问题,例如我们对年龄特征分为5段,只允许5个值有且只有1个值为1, #Softmax本身的算法很简单,就是把所有值用e的n次方计算出来,求和后算每个值占的比率,保证总和为1,一般可以认为Softmax出来的就是confidence也就是概率 #softmax_cross_entropy_with_logits和sigmoid_cross_entropy_with_logits很不一样,输入是类似的logits和lables的shape一样,但这里要求分类的结果是互斥的, # 保证只有一个字段有值,例如CIFAR-10中图片只能分一类而不像前面判断是否包含多类动物。想一下问什么会有这样的限制?在函数头的注释中我们看到, # 这个函数传入的logits是unscaled的,既不做sigmoid也不做softmax,因为函数实现会在内部更高效得使用softmax, # 对于任意的输入经过softmax都会变成和为1的概率预测值,这个值就可以代入变形的Cross Entroy算法- y * ln(a) - (1 - y) * ln(1 - a)算法中, # 得到有意义的Loss值了。如果是多目标问题,经过softmax就不会得到多个和为1的概率,而且label有多个1也无法计算交叉熵, # 因此这个函数只适合单目标的二分类或者多分类问题 #再补充一点,对于多分类问题,例如我们的年龄分为5类,并且人工编码为0、1、2、3、4,因为输出值是5维的特征, # 因此我们需要人工做onehot encoding分别编码为00001、00010、00100、01000、10000,才可以作为这个函数的输入。 # 理论上我们不做onehot encoding也可以,做成和为1的概率分布也可以,但需要保证是和为1,和不为1的实际含义不明确, #tf.nn.sparse_softmax_cross_entropy_with_logits #sparse_softmax_cross_entropy_with_logits是softmax_cross_entropy_with_logits的易用版本,除了输入参数不同,作用和算法实现都是一样的。 # 前面提到softmax_cross_entropy_with_logits的输入必须是类似onehot encoding的多维特征, # 但CIFAR-10、ImageNet和大部分分类场景都只有一个分类目标,label值都是从0编码的整数,每次转成onehot encoding比较麻烦,有没有更好的方法呢? # 答案就是用sparse_softmax_cross_entropy_with_logits,它的第一个参数logits和前面一样,shape是[batch_size, num_classes], # 而第二个参数labels以前也必须是[batch_size, num_classes]否则无法做Cross Entropy, # 这个函数改为限制更强的[batch_size],而值必须是从0开始编码的int32或int64,而且值范围是[0, num_class),如果我们从1开始编码或者步长大于1, # 会导致某些label值超过这个范围,代码会直接报错退出。这也很好理解,TensorFlow通过这样的限制才能知道用户传入的3、6或者9对应是哪个class, # 最后可以在内部高效实现类似的onehot encoding,这只是简化用户的输入而已, # 如果用户已经做了onehot encoding那可以直接使用不带“sparse”的softmax_cross_entropy_with_logits函数。 #tf.nn.weighted_cross_entropy_with_logits #weighted_sigmoid_cross_entropy_with_logits是sigmoid_cross_entropy_with_logits的拓展版,输入参数和实现和后者差不多, # 可以多支持一个pos_weight参数,目的是可以增加或者减小正样本在算Cross Entropy时的Loss。 # 实现原理很简单,在传统基于sigmoid的交叉熵算法上,正样本算出的值乘以某个系数接口. #这就是TensorFlow目前提供的有关Cross Entropy的函数实现,用户需要理解多目标和多分类的场景, # 根据业务需求(分类目标是否独立和互斥)来选择基于sigmoid或者softmax的实现, # 如果使用sigmoid目前还支持加权的实现,如果使用softmax我们可以自己做onehot coding # 或者使用更易用的sparse_softmax_cross_entropy_with_logits函数。 #TensorFlow提供的Cross Entropy函数基本cover了多目标和多分类的问题,但如果同时是多目标多分类的场景, # 肯定是无法使用softmax_cross_entropy_with_logits,如果使用sigmoid_cross_entropy_with_logits # 我们就把多分类的特征都认为是独立的特征,而实际上他们有且只有一个为1的非独立特征,计算Loss时不如Softmax有效。 # Define optimizer optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost) # SGD(文献5,6) #x+= -learning_rate*dx # optimizer = tf.train.GradientDescentOptimizer(learning_rate=self.learning_rate) # # Momentum # # optimizer = tf.train.MomentumOptimizer(lr, 0.9) # # AdaGrad # # optimizer = tf.train.AdagradientOptimizer(learning_rate=self.learning_rate) # # RMSProp # # optimizer = tf.train.RMSPropOptimizer(0.001, 0.9) # # ADAM # # optimizer = tf.train.AdamOptimizer(learning_rate=self.learning_rate, epsilon=1e-08) # Initializing the variables初始化化所有变量 init = tf.global_variables_initializer() # Launch the graph with tf.Session() as sess: #初始化化所有变量 sess.run(init) # Training cycle for epoch in range(training_epochs): avg_cost = 0. total_batch = int(mnist.train.num_examples/batch_size) # Loop over all batches one by one,把数据分块做训练 for i in range(total_batch): batch_x, batch_y = mnist.train.next_batch(batch_size) # Run optimization op (backprop) and cost op (to get loss value),feed_dict,是把数据喂给分类器 _, c = sess.run([optimizer, cost], feed_dict={x: batch_x, y: batch_y}) # Compute average loss avg_cost += c / total_batch # Display logs per epoch step if epoch % display_step == 0: print("Epoch:", '%04d' % (epoch+1), "cost=", \ "{:.9f}".format(avg_cost)) print("Optimization Finished!") # Test model测试数据,找出pred的最大好 correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)) # Calculate accuracy accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) print("Accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels})) #http://www.jiqizhixin.com/article/1440 基础tensorflow #http://weibo.com/ttarticle/p/show?id=2309404047468714166594 TensorFlow四种Cross Entropy算法实现和应用 #https://www.tensorflow.org/versions/master/api_docs/python/nn.html#sparse_softmax_cross_entropy_with_logits 官方文档 #https://jamesmccaffrey.wordpress.com/2013/11/05/why-you-should-use-cross-entropy-error-instead-of-classification-error-or-mean-squared-error-for-neural-network-classifier-training/ 为什么: 平方差表达预测值与真实值的差异,但在分类问题种效果并不如交叉熵好 #http://blog.csdn.net/csyanbin/article/details/53460627 优化方法
#http://sebastianruder.com/optimizing-gradient-descent/index.html#gradientdescentvariants 优化算法
#图片来自小象学院ptt
版权声明:本文为yuzhou164原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。