智障自学深度学习系列-1 MNIST

安装 TensorFlow 会另外单独讲,这里零碎记录 http://wiki.jikexueyuan.com/project/tensorflow-zh/ 开始的流程。

首先会跑一个 hello world,注意这里原本是 Python 2.x 的代码,我已经修改为 Python 3.x 代码了:

# http://wiki.jikexueyuan.com/project/tensorflow-zh/
# Python 3.x  edit by Dr_David_S
# CSDN blog http://blog.csdn.net/qq_27469517

import tensorflow as tf
import numpy as np

# 使用 NumPy 生成假数据(phony data), 总共 100 个点.
x_data = np.float32(np.random.rand(2, 100)) # 随机输入浮点数,2行100列
y_data = np.dot([0.100, 0.200], x_data) + 0.300 # 点积,矩阵乘法,输出一个1行100列矩阵


# 构造一个线性模型
# 
b = tf.Variable(tf.zeros([1]))
W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0))
y = tf.matmul(W, x_data) + b # 神经网络就是预测这里的 W , x_data 和 b

# 最小化方差
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

# 初始化变量
init = tf.initialize_all_variables()

# 启动图 (graph)
sess = tf.Session()
sess.run(init)

# 拟合平面
for step in range(0, 201): # 原文是xrange(0,201),运行200次
    sess.run(train)
    if step % 20 == 0:
        print (step, sess.run(W), sess.run(b))

# 得到最佳拟合结果 W: [[0.100  0.200]], b: [0.300]


接下来是 MNIST 数据集,一个手写数字识别:

首先创建input_data.py


input_data 会在当前目录下创建一个名叫 MNIST_data 的文件夹,下载四个 .gz 压缩文件

如果不能科学上网,很可能下载失败,大家可以去网上找别的下载。注意不要自己解压。

# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================

"""Functions for downloading and reading MNIST data."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import gzip
import os
import tempfile

import numpy
from six.moves import urllib
from six.moves import xrange  # pylint: disable=redefined-builtin
import tensorflow as tf
from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets



然后:

# http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_download.html
# MNIST 数据集下载
# 源码: http://tensorflow/g3doc/tutorials/mnist/

import tensorflow as tf

# one-hot向量除了某一位的数字是1以外其余各维度数字都是0

import tensorflow.examples.tutorials.mnist.input_data as input_data # 导入 MNIST 数据集
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) 

# 60000 行训练数据集,每张图 28*28=784 像素
# 通过操作符号变量来描述这些可交互的操作单元,创建方法如下:
x = tf.placeholder(tf.float32, [None, 784])
# x 是一个占位符
# 张量的形状是[None,784 ],None 指代任何长度

# Variable代表一个可修改的张量,模型参数可以用这个类型
W = tf.Variable(tf.zeros([784,10])) # 权重值,维度[784,10],有784个特征和10个输出值
b = tf.Variable(tf.zeros([10])) # 偏置量,形状[10](10个数字)

# 实现模型
# 用tf.matmul(​​X,W)表示x乘以W,再加上b,把和输入到tf.nn.softmax函数里面
y = tf.nn.softmax(tf.matmul(x,W) + b)

# 交叉熵 https://www.zhihu.com/question/41252833
# 添加一个新的占位符用于输入正确值:
y_ = tf.placeholder("float", [None,10])
#计算交叉熵
# 用 tf.log 计算 y 的每个元素的对数。接下来,把 y_ 的每一个元素和 tf.log(y) 的对应元素相乘
# 最后,用 tf.reduce_sum 计算张量的所有元素的总和(100幅图片的)
cross_entropy = -tf.reduce_sum(y_*tf.log(y))

# BP神经网络-反向传播算法 https://www.zhihu.com/question/27239198?rf=24827633
# 梯度下降算法GDA,学习速率(步长)为0.01,用以最小化交叉熵。
# 调整代码可以使用其他优化算法:http://wiki.jikexueyuan.com/project/tensorflow-zh/api_docs/python/train.html
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

# 添加一个操作来初始化我们创建的变量:
init = tf.global_variables_initializer()
# tf.initialize_all_variables() 该函数以后会被 tf.global_variables_initializer() 代替

# 在一个Session里面启动我们的模型,并且初始化变量:
sess = tf.Session()
sess.run(init)

# 训练模型,1000次循环:
# 随机抓取训练数据中的100个批处理数据点
# 然后用这些数据点作为参数替换之前的占位符来运行train_step
for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100) # 每一次加载100个训练样本
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

# 评估模型
# tf.argmax(y,1)返回的是模型对于任一输入x预测到的标签值
# tf.argmax(y_,1) 代表正确的标签
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) # 返回True 或者 False
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) # 转换为浮点取平均值
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

# 结果在 0.91 左右


======================================================

接下来是深入MNIST数据集:

在上一步的Sofamax回归函数基础上增加了多层的神经网络,多次训练后效果明显变好,就是CPU训练很慢。还有如果电脑内存不够会卡死。

# http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_pros.html
# https://www.zhihu.com/question/46889310/answer/106295191 知乎参考
 
import tensorflow.examples.tutorials.mnist.input_data as input_data # 导入 MNIST 数据集
mnist = input_data.read_data_sets('./MNIST_data/', one_hot=True)
 
import tensorflow as tf
sess = tf.InteractiveSession() 
# InteractiveSession 比 Session 更灵活
# 如果没有使用InteractiveSession,那么你需要在启动session之前构建整个计算图,然后启动该计算图。
 
# 构建Softmax 回归模型
# 占位符
x = tf.placeholder("float", shape=[None, 784])
y_ = tf.placeholder("float", shape=[None, 10])
 
# 参数
# 初始化为 0 向量
W = tf.Variable(tf.zeros([784,10])) # 权重值,有784个特征和10个输出值
b = tf.Variable(tf.zeros([10])) # 偏置量,有10个分类
 
# 变量初始化
sess.run(tf.global_variables_initializer())
 
# 实现模型
# 把向量化后的图片x和权重矩阵W相乘,加上偏置b
y = tf.nn.softmax(tf.matmul(x,W) + b)
 
# 交叉熵
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
 
# 训练模型
# 梯度下降法
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
 
for i in range(1000):
    batch = mnist.train.next_batch(50) # 每次50个训练样本
    train_step.run(feed_dict={x: batch[0], y_: batch[1]})
 
# 评估模型
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) # 预测值和真实值 equal(),返回一个 bool 数组
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) # 计算准确率
print(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
# eval()的 source 这里是 accuracy, globals 必须是一个字典

print("以上是基础 MNIST 结果,直接使用 Softmax 回归模型。") 
print("现在构建一个两层卷积网络,看看效果:")
# 现在构建一个多层卷积网络
# ReLU神经元 
 
# 定义初始化函数
def weight_variable(shape): # 权重初始化 
    initial = tf.truncated_normal(shape, stddev=0.1) # 产生正态分布
    # tf.truncated_normal(shape, mean, stddev) :shape表示生成张量的维度,mean是均值,stddev是标准差。
    return tf.Variable(initial)
 
def bias_variable(shape): # 偏置初始化
    initial = tf.constant(0.1, shape=shape)
    # tf.constant(value,dtype=None,shape=None,name='Const'): 
    # 创建一个常量tensor,先给出value,可以设定其shape,比如可以是一维向量或者二维矩阵
    return tf.Variable(initial)
 
# 卷积使用1步长(stride size),0边距(padding size)的模板,保证输出和输入是同一个大小
def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
    # tf.nn.conv2d是TensorFlow里面实现卷积的函数
    # input = x, filter = W, strides = [1, 1, 1, 1],padding = 'SAME'
    # http://blog.csdn.net/mao_xiao_feng/article/details/53444333
 
def max_pool_2x2(x):
    # max pooling是CNN当中的最大值池化操作
    # http://blog.csdn.net/mao_xiao_feng/article/details/53453926
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                           strides=[1, 2, 2, 1], padding='SAME')
    # pooling的结果是使得特征减少,参数减少
 
# 第一层卷积
W_conv1 = weight_variable([5, 5, 1, 32]) # 权重初始化
# [5, 5, 1, 32] 前两个维度是patch的大小,接着是输入的通道数目,最后是输出的通道数目
b_conv1 = bias_variable([32]) # 偏置量初始化,算出32个特征,为了速度改为6
 
# x变成一个4d向量,其第2、第3维对应图片的宽、高,最后一维代表图片的颜色通道数
x_image = tf.reshape(x, [-1,28,28,1]) # 灰阶图通道数为 1
 
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) # 应用ReLU激活函数,ReUL:修正线性单元
# 没做预训练情况下,ReLu激活网络遥遥领先其它激活函数 http://www.cnblogs.com/neopenx/p/4453161.html
h_pool1 = max_pool_2x2(h_conv1) # 进行max pooling
 
 
# 第二层卷积
W_conv2 = weight_variable([5, 5, 32, 64]) # 输入的通道数目32,输出的通道数目64
b_conv2 = bias_variable([64]) # 每个5x5的patch会得到64个特征,为了速度改为12

 
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
 
# 密集连接层
W_fc1 = weight_variable([7 * 7 * 64, 1024]) # 图片尺寸减小到7x7,加入一个有1024个神经元的全连接层
b_fc1 = bias_variable([1024])
 
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64]) # 把池化层输出的张量reshape成一些向量
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) # 加上权重矩阵和偏置
 
# Dropout 减少过拟合
# http://blog.csdn.net/stdcoutzyx/article/details/49022443
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

# 添加一个softmax层,就像前面的单层softmax regression一样
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])


y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) # 模型公式

# Adam是一种基于一阶梯度来优化随机目标函数的算法
# 交叉熵
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv)) # tf.reduce_sum 计算张量的所有元素的总和
# http://blog.csdn.net/xierhacker/article/details/53174558 Adam优化器
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
# 使用minimize()操作,该操作不仅可以计算出梯度,而且还可以将梯度作用在变量上 
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
sess.run(tf.global_variables_initializer())
# 开始训练
for i in range(1000): # 循环多少次,原文是20000,这里我改为1000
    batch = mnist.train.next_batch(50) # 每次读入50样本
    if i%100 == 0: # 每 100 次
        train_accuracy = accuracy.eval(feed_dict={
            x:batch[0], y_: batch[1], keep_prob: 1.0}) # keep_prob 控制 dropout 比例,输入层更接近1.0
        print("step %d, training accuracy %g"%(i, train_accuracy))
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5}) # 隐含层一般设为0.5

# 输出测试集准确度
print("test accuracy %g"%accuracy.eval(feed_dict={
      x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
# 5000次效果大概在 0.98 左右

于是我缩减了神经元数量:

# http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_pros.html
# https://www.zhihu.com/question/46889310/answer/106295191 知乎参考
 
import tensorflow.examples.tutorials.mnist.input_data as input_data # 导入 MNIST 数据集
mnist = input_data.read_data_sets('./MNIST_data/', one_hot=True)
 
import tensorflow as tf
sess = tf.InteractiveSession() 
# InteractiveSession 比 Session 更灵活
# 如果没有使用InteractiveSession,那么你需要在启动session之前构建整个计算图,然后启动该计算图。
 
# 构建Softmax 回归模型
# 占位符
x = tf.placeholder("float", shape=[None, 784])
y_ = tf.placeholder("float", shape=[None, 10])
 
# 参数
# 初始化为 0 向量
W = tf.Variable(tf.zeros([784,10])) # 权重值,有784个特征和10个输出值
b = tf.Variable(tf.zeros([10])) # 偏置量,有10个分类
 
# 变量初始化
sess.run(tf.global_variables_initializer())
 
# 实现模型
# 把向量化后的图片x和权重矩阵W相乘,加上偏置b
y = tf.nn.softmax(tf.matmul(x,W) + b)
 
# 交叉熵
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
 
# 训练模型
# 梯度下降法
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
 
for i in range(1000):
    batch = mnist.train.next_batch(50) # 每次50个训练样本
    train_step.run(feed_dict={x: batch[0], y_: batch[1]})
 
# 评估模型
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) # 预测值和真实值 equal(),返回一个 bool 数组
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) # 计算准确率
print(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
# eval()的 source 这里是 accuracy, globals 必须是一个字典

print("以上是基础 MNIST 结果,直接使用 Softmax 回归模型。") 
print("现在构建一个两层卷积网络,看看效果:")
# 现在构建一个多层卷积网络
# ReLU神经元 
 
# 定义初始化函数
def weight_variable(shape): # 权重初始化 
    initial = tf.truncated_normal(shape, stddev=0.1) # 产生正态分布
    # tf.truncated_normal(shape, mean, stddev) :shape表示生成张量的维度,mean是均值,stddev是标准差。
    return tf.Variable(initial)
 
def bias_variable(shape): # 偏置初始化
    initial = tf.constant(0.1, shape=shape)
    # tf.constant(value,dtype=None,shape=None,name='Const'): 
    # 创建一个常量tensor,先给出value,可以设定其shape,比如可以是一维向量或者二维矩阵
    return tf.Variable(initial)
 
# 卷积使用1步长(stride size),0边距(padding size)的模板,保证输出和输入是同一个大小
def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
    # tf.nn.conv2d是TensorFlow里面实现卷积的函数
    # input = x, filter = W, strides = [1, 1, 1, 1],padding = 'SAME'
    # http://blog.csdn.net/mao_xiao_feng/article/details/53444333
 
def max_pool_2x2(x):
    # max pooling是CNN当中的最大值池化操作
    # http://blog.csdn.net/mao_xiao_feng/article/details/53453926
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                           strides=[1, 2, 2, 1], padding='SAME')
    # pooling的结果是使得特征减少,参数减少
 
# 第一层卷积
# W_conv1 = weight_variable([5, 5, 1, 32]) # 权重初始化
W_conv1 = weight_variable([5, 5, 1, 12])
# [5, 5, 1, 32] 前两个维度是patch的大小,接着是输入的通道数目,最后是输出的通道数目
# b_conv1 = bias_variable([32]) # 偏置量初始化,算出32个特征,为了速度改为12
b_conv1 = bias_variable([12])
 
# x变成一个4d向量,其第2、第3维对应图片的宽、高,最后一维代表图片的颜色通道数
x_image = tf.reshape(x, [-1,28,28,1]) # 灰阶图通道数为 1
 
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) # 应用ReLU激活函数,ReUL:修正线性单元
# 没做预训练情况下,ReLu激活网络遥遥领先其它激活函数 http://www.cnblogs.com/neopenx/p/4453161.html
h_pool1 = max_pool_2x2(h_conv1) # 进行max pooling
 
 
# 第二层卷积
# W_conv2 = weight_variable([5, 5, 32, 64]) # 输入的通道数目32,输出的通道数目64
W_conv2 = weight_variable([5, 5, 12, 24])
# b_conv2 = bias_variable([64]) # 每个5x5的patch会得到64个特征,为了速度改为24
b_conv2 = bias_variable([24])
 
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
 
# 密集连接层
# W_fc1 = weight_variable([7 * 7 * 64, 1024]) # 图片尺寸减小到7x7,加入一个有1024个神经元的全连接层
# b_fc1 = bias_variable([1024])
W_fc1 = weight_variable([7 * 7 * 24, 512])
b_fc1 = bias_variable([512])
 
# h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64]) # 把池化层输出的张量reshape成一些向量
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 24])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) # 加上权重矩阵和偏置
 
# Dropout 减少过拟合
# http://blog.csdn.net/stdcoutzyx/article/details/49022443
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

# 添加一个softmax层,就像前面的单层softmax regression一样
# W_fc2 = weight_variable([1024, 10])
W_fc2 = weight_variable([512, 10])
# b_fc2 = bias_variable([10])
b_fc2 = bias_variable([10])

y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) # 模型公式

# Adam是一种基于一阶梯度来优化随机目标函数的算法
# 交叉熵
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv)) # tf.reduce_sum 计算张量的所有元素的总和
# http://blog.csdn.net/xierhacker/article/details/53174558 Adam优化器
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
# 使用minimize()操作,该操作不仅可以计算出梯度,而且还可以将梯度作用在变量上 
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
sess.run(tf.global_variables_initializer())
# 开始训练
for i in range(1000): # 循环多少次,原文是20000
    batch = mnist.train.next_batch(50) # 每次读入50样本
    if i%100 == 0: # 每 100 次
        train_accuracy = accuracy.eval(feed_dict={
            x:batch[0], y_: batch[1], keep_prob: 1.0}) # keep_prob 控制 dropout 比例,输入层更接近1.0
        print("step %d, training accuracy %g"%(i, train_accuracy))
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5}) # 隐含层一般设为0.5

# 输出测试集准确度
print("test accuracy %g"%accuracy.eval(feed_dict={
      x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
# 1层6神经元,2层12神经元,softmax层参数128,1000次效果大概在 0.90 左右
# 1层12神经元,2层24神经元,softmax层参数512,1000次效果大概在 0.95 左右
# 原来的代码跑完机器跟废了一样的原因应该是神经元太多,内存不够

概念挺多的,比如交叉熵什么的之前都不知道...后来补了一下,可以去百度看看。

交叉熵是信息理论中的概念,可以让我们描述如果基于已有事实,相信神经网络所做的推测最坏会导致什么结果


池化:

http://www.cnblogs.com/believe-in-me/p/6645402.html  

http://blog.csdn.net/liulina603/article/details/47727277参见这里


softmax 回归:该模型是logistic回归模型在多分类问题上的推广,在多分类问题中,类标签 y可以取两个以上的值。可以认为是logistic回归对多分类问题的推广,当是两分类时,就是logistic回归。相比训练多个logistic回归来做多分类,softmax回归更适合类别间是互斥的,比如字符识别。


各种Optimizer方法:比如梯度下降法GradientDescentOptimizerAdamOptimizer等等。http://blog.csdn.net/lenbow/article/details/52218551






你可能感兴趣的:(人工智障)