写给小白的TensorFlow的入门课

文章目录

    • 前言
    • 学习AI的必要性
      • 和业务的关系
    • 最简单的例子
      • 要做什么?
      • 数据图形化展示
      • 构建计算图形
      • 计算图形
      • 最小化误差
    • MacOS 中配置运行环境
      • 安装
      • 验证安装
    • 简单模型训练
    • 识别数字图片的模型训练
      • Softmax Regression算法
      • 大概步骤
      • 大致算法
      • 实现
    • 结语
    • 参考链接

前言

深度学习就是从大量数据中寻找规律,学习什么?学习模型的各种参数。从训练模型到模型推理,都离不开深度学习框架。TensorFlow和PyTorch就是两个最主要的框架。
AI的模型训练其实就是: 对模型变量的值进行不断调整,直到训练模型对所有可能的变量求出的结果都无限接近目标值,而我们要做的工作就是给足够的数据进行训练,以及不断优化训练算法。

学习AI的必要性

自从2016年AlphaGo战胜李世石后,人工智能,深度学习成为最热门的话题。但是其实深度学习其实很早就有,在2012年的ImageNet图像分类竞赛中,深度学习系统AlexNet夺冠其实已经预示着深度学习开启的AI新时代即将到来。

作为一个IT从业人员,如何理解新的AI时代对我们的影响,先看一下下图的数据:

写给小白的TensorFlow的入门课_第1张图片

此图是google内部使用tensorflow(机器学习)的状况,整个以指数形进行增长。2016年Q1的时候已经超过2000的项目在使用。人工智能已经变成了一种基础设施,每一个开发&测试都应该有所了解。

和业务的关系

那作为普通的业务开发&测试人员,AI和我们关系如何呢?整理了一下AI对业务的关系,可以理解为如下图:

  • 算法:根据不同的使用场景,使用不同的算法来进行支撑,因为tensorflow等开源框架的支持,这部分的成本已经大大降低。
  • 计算:机器学习特别是深度学习需要巨大的计算能力,但是现在使用阿里云等云计算平台的计算成本大大减低,这块也逐渐不在成为瓶颈。
  • 数据:这块和各个业务关联性比较大,也是各业务可以利用AI的能力来进行创新的关键,只要结合自己的业务和数据,利用AI能力就能带来很多不一样的突破。

写给小白的TensorFlow的入门课_第2张图片

最简单的例子

Tensorflow是google的开源的人工智能学习系统,下面是一个Tensorflow版本的Helloworld列子,让大家对其有个基本的了解。

要做什么?

待预测的方程:y=0.7x+0.3+noise
模型:y=Wx+b
目标:通过给出足够的x,y,预测出W和b.
模拟数据准备:

import numpy as np
 
# 创建200个随机的值,为了模拟真实情况,增加noise y = x * 0.7 + 0.3
x_data = np.random.rand(200).astype(np.float32)

noise = np.random.normal(0,0.01,x_data.shape)

y_data = x_data * 0.7 + 0.3 + noise

数据图形化展示

写给小白的TensorFlow的入门课_第3张图片

构建计算图形

import tensorflow as tf
 
x = tf.placeholder(shape=[None],
                    dtype=tf.float32,name=‘x')

W = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) 

b = tf.Variable(tf.zeros([1])) 

y = W * x + b

计算图形

写给小白的TensorFlow的入门课_第4张图片

最小化误差

# Minimize the mean squared errors.

loss = tf.reduce_mean(tf.square(y - y_data))

optimizer = tf.train.GradientDescentOptimizer(0.5)

train = optimizer.minimize(loss)

计算图形如下:
写给小白的TensorFlow的入门课_第5张图片

MacOS 中配置运行环境

官方教程地址: https://www.tensorflow.org/install/install_mac#installing_with_virtualenv

一共有四种方式,根据官方推荐,我采用的是virtualenv

由于我的MBP没有NVIDIA CUDA GPU,因此这里我没有配GPU

安装

sudo easy_install pip

写给小白的TensorFlow的入门课_第6张图片

sudo pip install --upgrade virtualenv

写给小白的TensorFlow的入门课_第7张图片

virtualenv --system-site-packages tensorflow

tensorflow-sample-3.png

由于MacOS Sierra自带的Python是2.7.10版本,并且我的MBP没有支持GPU,因此执行:

pip install --upgrade tensorflow

如果是其他情况的请参照官方教程
写给小白的TensorFlow的入门课_第8张图片

验证安装

官方地址: https://www.tensorflow.org/install/install_mac#ValidateYourInstallation
写给小白的TensorFlow的入门课_第9张图片

简单模型训练

该案例来自官方的入门案例: https://www.tensorflow.org/get_started/get_started

以tf引入tensorflow:

import tensorflow as tf
定义可训练模型变量W与b:

# 类型为tf.float32初始值为0.3的可训练模型变量W
W = tf.Variable([.3], tf.float32)
# 类型为tf.float32初始值为-0.3的可训练模型变量b
b = tf.Variable([-.3], tf.float32)
定义输出目标变量y:

y = tf.placeholder(tf.float32)
定义距离目标变量的损失值loss:

# 每个输出值与对应目标值差平方的和
loss = tf.reduce_sum(tf.square(linear_model - y))
定义优化器:

# 通过以精度0.01的梯度下降
optimizer = tf.train.GradientDescentOptimizer(0.01)
# 通过优化器,让其距离目标值逐渐减小
train = optimizer.minimize(loss)
准备训练用的数据:

# 输入变量x的值序列
x_train = [1,2,3,4]
# 需要能够对应输出的目标值序列
y_train = [0,-1,-2,-3]
开始训练:

# 初始化可训练变量
init = tf.global_variables_initializer()
# 创建一个session
sess = tf.Session()
# 复位训练模型
sess.run(init)
for i in range(1000):
  # 喂训练数据
  sess.run(train, {x:x_train, y:y_train})
输出训练结果:

curr_W, curr_b, curr_loss  = sess.run([W, b, loss], {x:x_train, y:y_train})
# 最终结果当 W为-0.9999969、b为0.99999082,距离目标值(每个输出值与目标值差的平方和)为5.69997e-11
# 输出: W: [-0.9999969] b: [0.99999082] loss: 5.69997e-11
print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))

写给小白的TensorFlow的入门课_第10张图片

该次模型训练的性能决定因素是: 优化器选择、精度选择、训练数据

通过高级的接口快速的实现上面的模型训练

import tensorflow as tf
# Numpy通常用于加载,维护与预处理数据
import numpy as np
# 需求队列(还有很多其他类型的column)
features = [tf.contrib.layers.real_valued_column("x", dimension=1)]
# estimator是一个前端调用用于训练与评估的接口,这里有非常多预定义的类型,如Linear Regression, Logistic Regression, Linear Classification, Logistic Classification 以及各种各样的Neural Network Classifiers 与 Regressors. 这里我们用的是Linear Regression
estimator = tf.contrib.learn.LinearRegressor(feature_columns=features)
# TensorFlow有提供了许多工具方法来读写数据集,这里我们使用`numpy_input_fn`,我们不得不告诉方法一共有多少组(num_epochs),并且每组有多大(batch_size)
x = np.array([1., 2., 3., 4.])
y = np.array([0., -1., -2., -3.])
input_fn = tf.contrib.learn.io.numpy_input_fn({"x":x}, y, batch_size=4,
                                              num_epochs=1000)
# 我们可以通过传入训练所用的数据集调用1000次`fit`方法来一步步训练
estimator.fit(input_fn=input_fn, steps=1000)
# 评估目前模型训练的怎么样。实际运用中,我们需要一个独立的验证与测试数据集避免训练过渡(overfitting)
estimator.evaluate(input_fn=input_fn)

当然我们也可以通过tf.contrib.learn.Estimator这个高级接口,再使用低级接口来定制Linear Regressor算法模型(实际上内置的tf.contrib.learn.LinearRegressor也是继承自tf.contrib.learn.Estimator的)。当然我们不是通过继承,是通过提供model_fn来告诉他训练的步骤、如果评估等:

import numpy as np
import tensorflow as tf
# 定义需求队列(这里我们只需要一个featurex)
def model(features, labels, mode):
  # 构建线性模型
  W = tf.get_variable("W", [1], dtype=tf.float64)
  b = tf.get_variable("b", [1], dtype=tf.float64)
  y = W*features['x'] + b
  # 定义距离目标变量的距离
  loss = tf.reduce_sum(tf.square(y - labels))
  # 训练子图
  global_step = tf.train.get_global_step()
  optimizer = tf.train.GradientDescentOptimizer(0.01)
  train = tf.group(optimizer.minimize(loss),
                   tf.assign_add(global_step, 1))
  # ModelFnOps用于将各参数串起来
  return tf.contrib.learn.ModelFnOps(
      mode=mode, predictions=y,
      loss=loss,
      train_op=train)
 
estimator = tf.contrib.learn.Estimator(model_fn=model)
# 定义我们的训练用的数据集
x = np.array([1., 2., 3., 4.])
y = np.array([0., -1., -2., -3.])
input_fn = tf.contrib.learn.io.numpy_input_fn({"x": x}, y, 4, num_epochs=1000)
# 训练
estimator.fit(input_fn=input_fn, steps=1000)

# 评估训练模型
print(estimator.evaluate(input_fn=input_fn, steps=10))

识别数字图片的模型训练

该模型训练是通过MNIST数据,使用Softmax Regressio算法训练一个输入784像素的图片,识别出其对应数字的模型。

写给小白的TensorFlow的入门课_第11张图片

MNIST包含一个手写的数字,就好像:
写给小白的TensorFlow的入门课_第12张图片

这个案例是为了解答:

TensorFlow是怎么工作的?
机器学习的核心思想是什么?
你可以学习到:

MNIST数据、Softmax Regression算法
建立一个可以基于观察图片的每一个像素来识别数字的模型
通过模型浏览上千个案例来训练模型识别数字
通过测试数据,来验证模型的准确度
MNIST数据

数据是在Yann LeCun’s website: http://yann.lecun.com/exdb/mnist/

该数据分为三部分:

通过分离不同的数据,一部分用于训练,一部分用户测试,一部分用于学习,这样才能验证结果是训练的模型自己生成的。

mnist.train: 55_000个数据用于训练
mnist.test: 10_000个数据用于测试
minst.validation: 5_000个数据用于验证
每个数据有两部分:

手写数字的图片(x)(mnist.train.images、mnist.test.images): 28px * 28px = 784px
对应的标签(y)(mnist.train.labels、mnist.test.labels)
如数字1:

写给小白的TensorFlow的入门课_第13张图片

mnist.[train/test].images是一个tensor,由55_000个由784个点的二维数组组成,数组中的每个值代表每个像素点,像素点有色的根据浅到深是0到1,无色为0,每个数组所呈现的数字对应一个label,我们表示为[55000,784] 写给小白的TensorFlow的入门课_第14张图片

minst.[train/test].labels也是一个tensor,由55_000个由10个值的一维数组组成,数组中有且仅有一个为1,其余为0,数组的index表示标签所代表的数字,如3表示为[0,0,0,1,0,0,0,0,0,0]],我们表示为[55000,10] tensorflow-mnist-写给小白的TensorFlow的入门课_第15张图片

Softmax Regression算法

我们算法要尽量准确的通过图片(784个像素点)所呈现的,让结果中正确的数字所占的比例尽量的高,如给出的图片对应的数字是9,模型运算结果可能是: 80%的概率是9,5%概率是8,15%的概率是其他。

该算法使用场景: 从不同的事件中为一个对象分配可能性,因为该算法给我们一个0到1的列表,并且加起来等于1

大概步骤

总结输入的数据在各种分类中的证据(we add up the evidence of our input being in certain classes)
将证据转化为具体的可能性
做像素强度(intensities)的加权值,当图片的强度(intentsity)与某个分类不一致,其权重为负数,当有强有力的证据证明是在那个分类,其权重为正数

最终的模型权重

蓝色为正数权重,红色为负数

写给小白的TensorFlow的入门课_第16张图片

大致算法

下面算法图形中表示: 第i个类型、第j个像素、W为权重、x为输入的图片、b为偏移量

最终算法公式: y=softmax(Wx y = s o f t m a x ( W x + b)

写给小白的TensorFlow的入门课_第17张图片

写给小白的TensorFlow的入门课_第18张图片

写给小白的TensorFlow的入门课_第19张图片

实现

import tensorflow as tf
 
# 导入mnist数据
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
 
# 定义输入图片(tensor)变量x,其结构为任意个数的784个点的图片
x = tf.placeholder(tf.float32, [None, 784])
 
# 定义训练因素
W = tf.Variable(tf.zeros([784, 10])) # 定义权重W, 10张784个点的图片
b = tf.Variable(tf.zeros([10])) # 定义偏移量,0~9
 
# 导入公式 softmax(W * x + b)
y = tf.nn.softmax(tf.matmul(x, W) + b)
 
# 使用cross-entropy(一个常见的loss模型)来定义结果有多差(定义一个标准,这样Tensorflow才能通过不断减少这个差值,来接近最终我们想要的模型)
y_ = tf.placeholder(tf.float32, [None, 10]) # 定义正确的
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1])) # 导入croos-entropy公式
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) # 使用"梯度减少"算法通过0.5的减少比率来学习
 
sess = tf.InteractiveSession() # 在InteractiveSession中启动模型
tf.global_variables_initializer().run() # 初始化我们创建的模型
 
# 每一步我们通过训练的集合生成100个随机的数据,通过train_step喂乳数据到图片x与对应的表示的数字y_
for _ in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
 
# 验证模型训练结果
 
# tf.argmax(y, 1)是对所有输入模型认为的最有可能的结果,tf.argmax(y_,1)实际上对所有输入最有可能的结果,然后通过tf.equal判断两个是否相等
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
# 由于correct_prediction计算出来的是一个Boolean数组,因此我们要通过tf.cast将其转为float,如[True, False, True, True]应该转为[1, 0, 1, 1]其中1占其中的0.75
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
# 最后输出通过模型计算出来的正确率,这个模型的正确率会在92%左右
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

这边的正确率是92%,是由于我们的模型非常简单,最好的模型能够达到99.7%的正确率,可以看看网上的不同模型的测试结果: http://rodrigob.github.io/are_we_there_yet/build/classification_datasets_results.html

结语

这是本人整理的入门资料,还很粗糙,后续继续完善。

参考链接

  • MNIST For ML Beginners
  • TensorFlow Api Doc
  • Getting Started With TensorFlow

你可能感兴趣的:(人工智能,tensorflow,深度学习,python)