Tensorflow快餐教程(1) - 30行代码搞定手写识别

摘要: Tensorflow入门教程1

去年买了几本讲tensorflow的书,结果今年看的时候发现有些样例代码所用的API已经过时了。看来自己维护一个保持更新的Tensorflow的教程还是有意义的。这是写这一系列的初心。


快餐教程系列希望能够尽可能降低门槛,少讲,讲透。


为了让大家在一开始就看到一个美好的场景,而不是停留在漫长的基础知识积累上,参考网上的一些教程,我们直接一开始就直接展示用tensorflow实现MNIST手写识别的例子。然后基础知识我们再慢慢讲。

Tensorflow安装速成教程

由于Python是跨平台的语言,所以在各系统上安装tensorflow都是一件相对比较容易的事情。GPU加速的事情我们后面再说。

Linux平台安装tensorflow

我们以Ubuntu 16.04版为例,首先安装python3和pip3。pip是python的包管理工具。

sudo apt install python3
sudo apt install python3-pip

然后就可以通过pip3来安装tensorflow:

pip3 install tensorflow --upgrade

MacOS安装tensorflow

建议使用Homebrew来安装python。

brew install python3

安装python3之后,还是通过pip3来安装tensorflow.

pip3 install tensorflow --upgrade

Windows平台安装Tensorflow

Windows平台上建议通过Anaconda来安装tensorflow,下载地址在:https://www.anaconda.com/download/#windows

然后打开Anaconda Prompt,输入:

conda create -n tensorflow pip
activate tensorflow
pip install --ignore-installed --upgrade tensorflow

这样就安装好了Tensorflow。

我们迅速来个例子试下好不好用:

import tensorflow as tf
a = tf.constant(1)
b = tf.constant(2)c = a * bsess = tf.Session()print(sess.run(c))

输出结果为2. 
Tensorflow顾名思义,是一些Tensor张量的流组成的运算。
运算需要一个Session来运行。如果print(c)的话,会得到

Tensor("mul_1:0", shape=(), dtype=int32)

就是说这是一个乘法运算的Tensor,需要通过Session.run()来执行。

入门捷径:线性回归

我们首先看一个最简单的机器学习模型,线性回归的例子。
线性回归的模型就是一个矩阵乘法:

tf.multiply(X, w)

然后我们通过调用Tensorflow计算梯度下降的函数tf.train.GradientDescentOptimizer来实现优化。
我们看下这个例子代码,只有30多行,逻辑还是很清晰的。例子来自github上大牛的工作:https://github.com/nlintz/TensorFlow-Tutorials,不是我的原创。

import tensorflow as tf
import numpy as nptrX = np.linspace(-1, 1, 101)
trY = 2 * trX + np.random.randn(*trX.shape) * 0.33 # 创建一些线性值附近的随机值X = tf.placeholder("float") 
Y = tf.placeholder("float")def model(X, w):return tf.multiply(X, w) # X*w线性求值,非常简单w = tf.Variable(0.0, name="weights") 
y_model = model(X, w)cost = tf.square(Y - y_model) # 用平方误差做为优化目标train_op = tf.train.GradientDescentOptimizer(0.01).minimize(cost) # 梯度下降优化# 开始创建Session干活!
with tf.Session() as sess:# 首先需要初始化全局变量,这是Tensorflow的要求tf.global_variables_initializer().run()for i in range(100):for (x, y) in zip(trX, trY):sess.run(train_op, feed_dict={X: x, Y: y})print(sess.run(w)) 

最终会得到一个接近2的值,比如我这次运行的值为1.9183811

多种方式搞定手写识别

线性回归不过瘾,我们直接一步到位,开始进行手写识别。

我们采用深度学习三巨头之一的Yann Lecun教授的MNIST数据为例。如上图所示,MNIST的数据是28x28的图像,并且标记了它的值应该是什么。

线性模型:logistic回归

我们首先不管三七二十一,就用线性模型来做分类。
算上注释和空行,一共加起来30行左右,我们就可以解决手写识别这么困难的问题啦!请看代码:

import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_datadef init_weights(shape):return tf.Variable(tf.random_normal(shape, stddev=0.01))def model(X, w):return tf.matmul(X, w) # 模型还是矩阵乘法mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labelsX = tf.placeholder("float", [None, 784])
Y = tf.placeholder("float", [None, 10])w = init_weights([784, 10]) 
py_x = model(X, w)cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=py_x, labels=Y)) # 计算误差
train_op = tf.train.GradientDescentOptimizer(0.05).minimize(cost) # construct optimizer
predict_op = tf.argmax(py_x, 1) with tf.Session() as sess:tf.global_variables_initializer().run()for i in range(100):for start, end in zip(range(0, len(trX), 128), range(128, len(trX)+1, 128)):sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end]})print(i, np.mean(np.argmax(teY, axis=1) ==sess.run(predict_op, feed_dict={X: teX})))

经过100轮的训练,我们的准确率是92.36%。

无脑的浅层神经网络

用了最简单的线性模型,我们换成经典的神经网络来实现这个功能。神经网络的图如下图所示。


我们还是不管三七二十一,建立一个隐藏层,用最传统的sigmoid函数做激活函数。其核心逻辑还是矩阵乘法,这里面没有任何技巧。

    h = tf.nn.sigmoid(tf.matmul(X, w_h)) return tf.matmul(h, w_o) 

完整代码如下,仍然是40多行,不长:

import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data# 所有连接随机生成权值
def init_weights(shape):return tf.Variable(tf.random_normal(shape, stddev=0.01))def model(X, w_h, w_o):h = tf.nn.sigmoid(tf.matmul(X, w_h)) return tf.matmul(h, w_o) mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labelsX = tf.placeholder("float", [None, 784])
Y = tf.placeholder("float", [None, 10])w_h = init_weights([784, 625])
w_o = init_weights([625, 10])py_x = model(X, w_h, w_o)cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=py_x, labels=Y)) # 计算误差损失
train_op = tf.train.GradientDescentOptimizer(0.05).minimize(cost) # construct an optimizer
predict_op = tf.argmax(py_x, 1)with tf.Session() as sess:tf.global_variables_initializer().run()for i in range(100):for start, end in zip(range(0, len(trX), 128), range(128, len(trX)+1, 128)):sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end]})print(i, np.mean(np.argmax(teY, axis=1) ==sess.run(predict_op, feed_dict={X: teX})))

第一轮运行,我这次的准确率只有69.11% ,第二次就提升到了82.29%。最终结果是95.41%,比Logistic回归的强!
请注意我们模型的核心那两行代码,完全就是无脑地全连接做了一个隐藏层而己,这其中没有任何的技术。完全是靠神经网络的模型能力。

深度学习时代的方案 - ReLU和Dropout显神通

上一个技术含量有点低,现在是深度学习的时代了,我们有很多进步。比如我们知道要将sigmoid函数换成ReLU函数。我们还知道要做Dropout了。于是我们还是一个隐藏层,写个更现代一点的模型吧:

    X = tf.nn.dropout(X, p_keep_input)h = tf.nn.relu(tf.matmul(X, w_h))h = tf.nn.dropout(h, p_keep_hidden)h2 = tf.nn.relu(tf.matmul(h, w_h2))h2 = tf.nn.dropout(h2, p_keep_hidden)return tf.matmul(h2, w_o)

除了ReLU和dropout这两个技巧,我们仍然只有一个隐藏层,表达能力没有太大的增强。并不能算是深度学习。

import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_datadef init_weights(shape):return tf.Variable(tf.random_normal(shape, stddev=0.01))def model(X, w_h, w_h2, w_o, p_keep_input, p_keep_hidden): X = tf.nn.dropout(X, p_keep_input)h = tf.nn.relu(tf.matmul(X, w_h))h = tf.nn.dropout(h, p_keep_hidden)h2 = tf.nn.relu(tf.matmul(h, w_h2))h2 = tf.nn.dropout(h2, p_keep_hidden)return tf.matmul(h2, w_o)mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labelsX = tf.placeholder("float", [None, 784])
Y = tf.placeholder("float", [None, 10])w_h = init_weights([784, 625])
w_h2 = init_weights([625, 625])
w_o = init_weights([625, 10])p_keep_input = tf.placeholder("float")
p_keep_hidden = tf.placeholder("float")
py_x = model(X, w_h, w_h2, w_o, p_keep_input, p_keep_hidden)cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=py_x, labels=Y))
train_op = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)
predict_op = tf.argmax(py_x, 1)with tf.Session() as sess:# you need to initialize all variablestf.global_variables_initializer().run()for i in range(100):for start, end in zip(range(0, len(trX), 128), range(128, len(trX)+1, 128)):sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end],p_keep_input: 0.8, p_keep_hidden: 0.5})print(i, np.mean(np.argmax(teY, axis=1) ==sess.run(predict_op, feed_dict={X: teX,p_keep_input: 1.0,p_keep_hidden: 1.0})))

从结果看到,第二次就达到了96%以上的正确率。后来就一直在98.4%左右游荡。仅仅是ReLU和Dropout,就把准确率从95%提升到了98%以上。

卷积神经网络出场

真正的深度学习利器CNN,卷积神经网络出场。这次的模型比起前面几个无脑型的,的确是复杂一些。涉及到卷积层和池化层。这个是需要我们后面详细讲一讲了。

import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_databatch_size = 128
test_size = 256def init_weights(shape):return tf.Variable(tf.random_normal(shape, stddev=0.01))def model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden):l1a = tf.nn.relu(tf.nn.conv2d(X, w,                       # l1a shape=(?, 28, 28, 32)strides=[1, 1, 1, 1], padding='SAME'))l1 = tf.nn.max_pool(l1a, ksize=[1, 2, 2, 1],              # l1 shape=(?, 14, 14, 32)strides=[1, 2, 2, 1], padding='SAME')l1 = tf.nn.dropout(l1, p_keep_conv)l2a = tf.nn.relu(tf.nn.conv2d(l1, w2,                     # l2a shape=(?, 14, 14, 64)strides=[1, 1, 1, 1], padding='SAME'))l2 = tf.nn.max_pool(l2a, ksize=[1, 2, 2, 1],              # l2 shape=(?, 7, 7, 64)strides=[1, 2, 2, 1], padding='SAME')l2 = tf.nn.dropout(l2, p_keep_conv)l3a = tf.nn.relu(tf.nn.conv2d(l2, w3,                     # l3a shape=(?, 7, 7, 128)strides=[1, 1, 1, 1], padding='SAME'))l3 = tf.nn.max_pool(l3a, ksize=[1, 2, 2, 1],              # l3 shape=(?, 4, 4, 128)strides=[1, 2, 2, 1], padding='SAME')l3 = tf.reshape(l3, [-1, w4.get_shape().as_list()[0]])    # reshape to (?, 2048)l3 = tf.nn.dropout(l3, p_keep_conv)l4 = tf.nn.relu(tf.matmul(l3, w4))l4 = tf.nn.dropout(l4, p_keep_hidden)pyx = tf.matmul(l4, w_o)return pyxmnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels
trX = trX.reshape(-1, 28, 28, 1)  # 28x28x1 input img
teX = teX.reshape(-1, 28, 28, 1)  # 28x28x1 input imgX = tf.placeholder("float", [None, 28, 28, 1])
Y = tf.placeholder("float", [None, 10])w = init_weights([3, 3, 1, 32])       # 3x3x1 conv, 32 outputs
w2 = init_weights([3, 3, 32, 64])     # 3x3x32 conv, 64 outputs
w3 = init_weights([3, 3, 64, 128])    # 3x3x32 conv, 128 outputs
w4 = init_weights([128 * 4 * 4, 625]) # FC 128 * 4 * 4 inputs, 625 outputs
w_o = init_weights([625, 10])         # FC 625 inputs, 10 outputs (labels)p_keep_conv = tf.placeholder("float")
p_keep_hidden = tf.placeholder("float")
py_x = model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden)cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=py_x, labels=Y))
train_op = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)
predict_op = tf.argmax(py_x, 1)with tf.Session() as sess:# you need to initialize all variablestf.global_variables_initializer().run()for i in range(100):training_batch = zip(range(0, len(trX), batch_size),range(batch_size, len(trX)+1, batch_size))for start, end in training_batch:sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end],p_keep_conv: 0.8, p_keep_hidden: 0.5})test_indices = np.arange(len(teX)) # Get A Test Batchnp.random.shuffle(test_indices)test_indices = test_indices[0:test_size]print(i, np.mean(np.argmax(teY[test_indices], axis=1) ==sess.run(predict_op, feed_dict={X: teX[test_indices],p_keep_conv: 1.0,p_keep_hidden: 1.0})))

我们看下这次的运行数据:

0 0.95703125
1 0.9921875
2 0.9921875
3 0.98046875
4 0.97265625
5 0.98828125
6 0.99609375

在第6轮的时候,就跑出了99.6%的高分值,比ReLU和Dropout的一个隐藏层的神经网络的98.4%大大提高。因为难度是越到后面越困难。
在第16轮的时候,竟然跑出了100%的正确率:

7 0.99609375
8 0.99609375
9 0.98828125
10 0.98828125
11 0.9921875
12 0.98046875
13 0.99609375
14 0.9921875
15 0.99609375
16 1.0

综上,借助Tensorflow和机器学习工具,我们只有几十行代码,就解决了手写识别这样级别的问题,而且准确度可以达到如此程度。


本文作者:lusing

原文链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/521850.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

科普帖:什么是服务网格?

戳蓝字“CSDN云计算”关注我们哦!译| 风车云马文| Josh Fruhlinger来源| InfoWorld网站在数字化转型的背景下,IT行业正在将大型的应用程序集成到小的、离散的微服务容器中,这些容器包含所有的服务代码和依赖项,而这些依赖项彼此独…

年轻人,你为什么来阿里做技术?

摘要: 一个阿里IT男,成了母婴专家? 最近,阿里算法工程师拉普当上了爸爸。 两个月前他就开始为这件事忙活。自从老婆有喜之后,七大姑八大姨都来给他提供参考,生过孩子的朋友、同事都对他说什么该买,主管也时…

查一个字段中字符集超过30的列_详细解读MySQL的30条军规

一、基础规范(1)必须使用InnoDB存储引擎 解读:支持事务、行级锁、并发性能更好、CPU及内存缓存页优化使得资源利用率更高(2)必须使用UTF8字符集 解读:万国码,无需转码,无乱码风险&am…

ThinkPHP 5使用OSS

摘要: ThinkPHP 5使用OSS示例。准备工作登录阿里云官网,将鼠标移至产品找到并单击对象存储OSS打开OSS产品详情页面。在OSS产品详情页中的单击立即开通。开通服务后,在OSS产品详情页面单击管理控制台直接进入OSS管理控制台界面。您也可以单击位…

Linux环境_源码安装LibreOffice实现文件在线预览doc,doxc,xls,xlsx,ppt,pptx 文件

因业务需求需要,利用LibOffice可以打开的文档的转换。 服务器版本 环境系统版本LinuxRed Hat Enterprise Linux Server release 7.6 (Maipo)LinuxCentOS Linux release 7.6 需要准备软件包 软件及版本下载链接LibreOffice_6.3.2_Linux_x86-64_rpm.tar.gzhttps://w…

关于云原生需要了解什么

戳蓝字“CSDN云计算”关注我们哦!尽管随处可闻云原生,却鲜少有人告诉你到底什么是云原生,若是找资料来看,读完大多会感觉云缭雾绕,一知半解,总之虚得很,甚至会让你一度怀疑自己的智商&#xff0…

仅使用NumPy完成卷积神经网络CNN的搭建(附Python代码)

摘要: 现有的Caffe、TensorFlow等工具箱已经很好地实现CNN模型,但这些工具箱需要的硬件资源比较多,不利于初学者实践和理解。因此,本文教大家如何仅使用NumPy来构建卷积神经网络(Convolutional Neural Network , CNN&a…

SpringBoot 使用LibreOffice 在线预览 doc,doxc,xls,xlsx,ppt,pptx 文件

接上一篇:linux环境源码安装unoconv Linux环境_源码安装Unoconv实现文件在线预览doc,doxc,xls,xlsx,ppt,pptx 文件 https://gblfy.blog.csdn.net/article/details/103540694 接上一篇:linux环境…

裸辞面11家python公司,拿到4个offer!网友:买了简历置顶会员吗?

我一直认为,敢裸辞的只有2种人:1、能力足够强,即使裸辞也不会被财务问题所困,更不愁找工作。2、年轻气盛,遇到傻X领导和傻X同事,绝对0容忍!但是最近我在刷某乎的时候,发现了第三种人…

万用表怎么测电池内阻_数字万用表和指针万用表,两者怎么选?

​万用表又称为复用表、多用表、三用表、繁用表等,一般以测量电压、电流和电阻为主要目的。是一种多功能、多量程的测量仪表,可测量直流电流、直流电压、交流电流、交流电压、电阻和音频电平等,有的还可以测交流电流、电容量、电感量及半导体…

在Linux系统上安装Git

Git是目前流行的非常好用的版本控制工具,这里介绍两种安装方式,1、yum安装,2、从github上下载最新的源码编译后安装 文章目录一、yum安装二、从GitHub上下载最新的源码编译后安装1、下载tar包2、上传tar包3、解压压缩包4、进入到解压后的文件…

Michael Jordan:当下的AI其实都是伪“AI”

摘要: Michael Jordan认真的解读当下的AI到底是什么?人工智能(AI)是未来的趋势,这句话是技术人员、学者、记者和风险投资家一致赞同的。如同从技术学术领域跨越到普遍行业的许多词语一样,在使用这些词语的时…

如何提升员工体验 助力企业业务增长?这个棘手的问题终于被解决了!

戳蓝字“CSDN云计算”关注我们哦!相信大部分人都经历过入职第一天的手忙脚乱与无所适从,一份新的工作本就是一项全新的挑战,各种设备的安装与链接、安装适应任何新任务的应用流程,以及令人头疼的各种密码,凡此种种都为…

vb 打印机 任意尺寸_创新小黑管“省心省力”惠普Laser NS 1020 智能闪充激光打印机...

对于小型公司、个人工作室或者有打印需求的家庭用户来说,一款优秀的轻巧、便携的打印机必不可少。前不久,惠普推出了全新一代惠普Laser NS 1020打印机,采用突破性的智能闪充碳粉技术,可实现15秒充粉,简便省时&#xff…

隐私与机器学习,二者可以兼得吗?

摘要: 隐私数据与机器学习看似矛盾,其实不然。如何有效保护机器学习训练中的隐私数据?谷歌专家给出了答案——PATE框架,就算你不太懂隐私保护的知识,也可以通过PATE框架来保护机器学习里的训练数据。最近关于互联网隐私…

SpringBoot 深度调优,让你的项目飞起来!

文章目录项目调优一、修改配置文件项目调优 作为一名工程师,项目调优这事,是必须得熟练掌握的事情。 在SpringBoot项目中,调优主要通过配置文件和配置JVM的参数的方式进行。 一、修改配置文件 关于修改配置文件application.properties。 …

青年PM倪超:想让程序员多一点点幸福感

摘要: 本文主人公倪超,在内部,同事都习惯叫他花名银时,是阿里云产品经理。前不久,他所负责的企业级分布式应用服务EDAS,荣获了公司2018财年年度最佳产品奖。在五四青年节来临之际,我们有幸近距离…

C语言--if...else语句【语法讲解】

一.if...else语句的介绍 if…else 语句是编程中常用的一种分支语句,用于根据条件执行不同的操作。 它的基本语法如下: if (条件表达式) {// 当条件表达式为真时执行的代码块 } else {// 当条件表达式为假时执行的代码块 } 当条件表达式为真时&#xff…

黑苹果找不到触控板_猫和老鼠手游:好友位不足却找不到人开黑?玩家给好友系统支招...

猫追鼠,鼠躲猫,欢乐互动乐逍遥,欢迎你来到猫和老鼠游戏学院第126期。随着开学季的到来,我们在游戏中会发现一个有趣的现象:任何时候打开自己的好友界面,里面都是灰色一片,不可否认这确实和玩家群…

Serverless 的喧哗与骚动

戳蓝字“CSDN云计算”关注我们哦!导读:从 2016 年 AWS 发布 Lambda 以来,全世界的开发者和云厂商对 Serverless 的热情在不断高涨。假设不想在开发应用程序并将其部署在服务器上的过程细节上花费精力,是否有一种简单的架构模型能够…