从此文开始,本专栏将推出一系列深度学习与图像处理相关的教程文章。注重原理精讲和代码实现。实现框架将重点选择Tensorflow或Pytorch。
什么是机器学习?
传统的有监督机器学习可以归结为这样一个过程:
- 获取标记数据对
(x, y)
。 - 建立含参模型,描述数据对
(x, y)
之间的关系:\hat{y} = f(x; \theta)
。其中\theta
是待学习的参数。 - 利用众多标记数据对
\{(x_i, y_i) | i = 1, \cdots, N\}
通过梯度下降法训练得到合适的参数$\theta$,使得估计误差最小。也就是:\min_\theta \Vert \hat{y} - y \Vert_2^2
机器学习还包括半监督、无监督和强化学习等,这里暂不考虑。
线性回归原理
线性回归问题是最简单机器学习问题。它的任务是:给定一个线性模型和数据对,求解出模型的最优参数。
设有向量变量x \in R^{m}
,y \in R^n
,权重矩阵W \in R^{m \times n}
,偏倚向量b \in R^n
,他们服从线性模型
y = W x + b
线性回归问题是:给定多组观察数据(x_i, y_i), i = 1, \cdots, p
,求权重矩阵W
和偏倚向量b
。
为了将多组输入数据写入一个模型中,令X = (x_1^T, \cdots, x_p^T)^T
,Y = (y_1^T, \cdots,y_p^T)^T
,B = (b^T, \cdots,b^T)^T
,则线性模型估计输出为
\tilde{Y} = X W + B
故线性回归问题归结于求解如下优化问题
\min_{W, b} \Vert Y - \tilde{Y} \Vert_2^2
Tensorflow实现
用Tensorflow估计线性回归模型的参数:
# coding=UTF-8
from __future__ import print_function
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
# 运算设备 cpu
device = "/cpu:0"
# 预设的模型参数
weight = 5
bias = 1.9
# 根据线性模型生成训练数据 trX 和 trY
trX = np.linspace(-1, 1, 101)
trY = weight * trX + bias + np.random.rand(*trX.shape) * 0.33 # 对 trY 添加高斯噪声
# tf定义线性模型
def model(X, w, b):
return tf.multiply(X, w) + b
# tf定义占位符,用于输入数据,训练或测试
X = tf.placeholder("float")
Y = tf.placeholder("float")
# tf模型变量(也就是需要估计的参数)
w = tf.Variable(0.0, name="weights")
b = tf.Variable(0.0, name="bias")
y_model = model(X, w, b)
# tf损失函数
cost = tf.reduce_mean(tf.square(Y - y_model))
# tf优化算子:使用梯度下降法,步长0.01
train_op = tf.train.GradientDescentOptimizer(0.01).minimize(cost)
# 打包训练数据为二元组列表
tdata = zip(trX, trY)
# 开启tf会话
with tf.Session() as sess:
# 指定运算设备 (CPU或GPU)
with tf.device(device):
# 初始化所有tf变量
tf.global_variables_initializer().run()
# 迭代优化 30 个Epoch
for i in range(30):
# 迭代一个Epoch
for (x, y) in zip(trX, trY):
# 用数据 x,y 进行一次梯度下降
sess.run(train_op, feed_dict={X:x, Y: y})
# 打印当前的损失函数值
print(i, sess.run(cost, feed_dict={X:trX, Y:trY}))
# 打印对模型变量估计的结果
estimated_w = sess.run(w)
estimated_b = sess.run(b)
print("estimated_w = %f, estimated_b = %f\n" % (estimated_w, estimated_b)) # print estimated result of w
# 用估计的参数画出模型拟合数据的效果
modelY = estimated_w * trX + estimated_b
plt.figure()
plt.plot(trX, trY, 'ro')
plt.plot(trX, modelY, 'b-')
plt.show()
实验效果
程序运行的输出为:
0 4.06233
1 1.36456
2 0.381636
3 0.106645
4 0.0343513
5 0.0155213
6 0.0105695
7 0.00923523
8 0.00885943
9 0.00874572
10 0.00870772
11 0.00869348
12 0.00868756
13 0.00868489
14 0.00868362
15 0.008683
16 0.00868268
17 0.00868254
18 0.00868246
19 0.00868242
20 0.0086824
21 0.00868239
22 0.00868237
23 0.00868237
24 0.00868237
25 0.00868237
26 0.00868237
27 0.00868237
28 0.00868237
29 0.00868237
estimated_w = 4.989621, estimated_b = 2.052838
可以看到,随着迭代轮次的增加,模型的估计误差稳定在0.00868
左右。预测的参数值w=4.99,b=2.05
与设定的参数值5, 1.9
接近。
用估计的W,b
画出的直线与原始数据放在一起的效果:
本文说明了如何用Tensorflow完成机器学习中最简单的一个任务:线性回归。为之后更复杂的深度学习问题打下基础。