一、监督式机器学习的基本术语
1. 样本、特征、标签与模型
标签是我们要预测的真实事物:y线性回归中的y变量
特征是指用于描述数据的输入变量:xi 线性回归中的{x1,x2,...,xn}变量
样本是指数据的特征实例:x
- 有标签样本具有{特征, 标签}:{x, y} 用于训练模型
- 无标签样本具有{特征, ?}:{x, ?} 用于对新数据做出预测
模型可将样本映射到预测标签:y',由模型的内部参数定义,这些内部参数值是通过学习得到的。
2. 训练与损失
训练模型表示通过有标签样本来学习(确定)所有权重和偏差的理想值,在监督式学习中,机器学习算法通过以下方式构建模型:检查多个样本并尝试找出可最大限度减少损失的模型,这一过程称为经验风险最小化。
损失是一个数值,表示对于单个样本而言模型预测的准确程度。训练模型的目标是从所有样本中找到一组平均损失较小的权重和偏差。
定义损失函数
- L1损失:基于模型预测的值与标签的实际值之差的绝对值
- 平方损失:一种常见的损失函数,又称为L2损失
均方误差(MSE)指的是每个样本的平均平方损失
MSE = \frac{1}{N}\sum_{(x,y)∈D}(y - prediction(x))^2
3. 模型训练与降低损失
模型训练要点
- 对权重w和偏差b进行初始猜测
- 反复调整这些猜测
- 直到获得损失可能最低的权重和偏差为止
在学习优化过程中,机器学习系统可以不断迭代,直到总体损失不再变化或至少变化极其缓慢为止,这时候可以说该模型已收敛。
4. 梯度下降法
梯度:一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大。
5. 学习率与超参数
用梯度乘以一个称为学习速率(步长)的标量,以确定下一个点的位置
例如:如果梯度大小为2.5,学习速率为0.01,则梯度下降法算法会选择距离前一个点0.025的位置作为下一个点。
超参数是在开始学习过程之前设置值的参数,如:学习率、神经网络的隐含层数量等
二、线性回归问题TensorFlow实战
1. 产生人工数据集
单变量的线性方程可以表示为:y = w * x + b
本例通过生成人工数据集,随机生成一个近似采样随机分布,使得 w = 2.0, b = 1, 并加入一个噪声,噪声的最大振幅为0.4。
#在Jupyter中,使用matplotlib显示图像需要设为inline模式,否则不会显示图像
%matplotlib inline
import matplotlib.pyplot as plt #载入matplotlib
import numpy as np #载入numpy
import tensorflow as tf #载入TensorFlow
#设置随机数种子
np.random.seed(5)
#直接采用np生成等差数列的方法,生成100个点,每个点的取值在-1~1之间
x_data = np.linspace(-1, 1, 100)
#y = 2x + 1 + 噪声,其中,噪声的维度与x_data一致
y_data = 2 * x_data + 1.0 + np.random.randn(*x_data.shape) * 0.4
2. 利用matplotlib画图
#画出随机生成数据的散点图
plt.scatter(x_data, y_data)
#画出我们想要学习到的线性函数 y = 2x + 1
plt.plot(x_data, 2 * x_data + 1.0, color = 'red', linewidth = 3)
3. 定义模型
使机器自动求出最合适的 w 和 b,使得对于生成的100个样本,总损失最小。
#构建模型
#定义训练数据的占位符,x是特征值,y是标签值
x = tf.placeholder("float", name = "x")
y = tf.placeholder("float", name = "y")
#定义模型函数
def model(x, w, b):
return tf.multiply(x, w) + b
#定义模型结构
#构建线性函数的斜率,变量w
w = tf.Variable(1.0, name = "w0")
#构建线性函数的截距,变量b
b = tf.Variable(0.0, name = "b0")
#pred是预测值,前向计算
pred = model(x, w, b)
4. 模型训练
设置训练参数
#迭代次数(训练轮数)
train_epochs = 10
#学习率
learning_rate = 0.05
定义损失函数
- 损失函数用于描述预测值与真实值间的误差,从而指导模型收敛方向
- 常见损失函数:均方差和交叉熵
#采用均方差作为损失函数
loss_function = tf.reduce_mean(tf.square(y - pred)) #标签值和预测差值平方的均值
定义优化器,设置学习率和优化目标:最小化损失
#梯度下降优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function)
创建会话
#声明会话
sess = tf.Session()
#初始化所有变量
init = tf.global_variables_initializer()
sess.run(init)
迭代训练:设置迭代轮次,每次通过将样本逐个输入模型,进行梯度下降优化操作,每轮迭代后,绘制出模型曲线。
#step = 0 #记录训练步数
#loss_list = [] #用于保存loss值的列表
#开始训练,轮数为epoch,采用SGD随机梯度下降优化方法
for epoch in range(train_epochs):
for xs, ys in zip(x_data, y_data):
_, loss = sess.run([optimizer, loss_function], feed_dict={x: xs, y: ys})
#显示损失值loss
#display_step:控制报告的粒度
#例如,如果display_step设为2,则将每训练2个样本输出一次损失值
#与超参数不同,修改display_step不会更改模型所学习的规律
#loss_list.append(loss)
#step = step + 1
#if step % display_step == 0:
# print("Train Epoch:", '%02d' %(epoch+1), "Step: %03d" %(step), "loss=",\
# "{:.9f}".format(loss))
#图形化显示损失值:plt.plot(loss_list,'r+')
b0temp = b.eval(session=sess)
w0temp = w.eval(session=sess)
plt.plot(x_data, w0temp * x_data + b0temp) #画图
[注]:本案例训练轮数设置为10,然而只出现了3根直线(其它覆盖了),说明训练3次后已接近收敛。
结果查看和可视化:训练完成后,打印查看参数(数据每次运行会有所不同,机器自动调整赋值w、b)
#查看结果:本例是通过逐渐降低损失值来训练参数 w和b 拟合 y = 2x + 1 中的系数 2 和 1
print("w:", sess.run(w)) #w的值应该在2附近
print("b:", sess.run(b)) #b的值应该在1附近
#结果可视化
plt.scatter(x_data, y_data, label = 'Original data') #原始散点图
plt.plot(x_data, x_data * sess.run(w) + sess.run(b), \
label = 'Fitted line', color = 'r', linewidth = 3)
#优化出来的 w、b画出来的直线(TensorFlow线性拟合)
plt.legend(loc=2) #通过参数loc指定图例位置
利用模型进行预测
#利用模型进行预测
x_test = 3.21
predict = sess.run(pred, feed_dict = {x: x_test})
print("预测值:%f" % predict)
target = 2 * x_test + 1.0
print("目标值: %f" % target)
# 预测值:7.405184
# 目标值: 7.420000