机器利用数据学习的过程
- 建立模型
y=wx+b
- 学习模型确定
w,b
- 预测或识别
- 在上述三个步骤中,最关键的就是第二步。如何从数据中产生模型是机器学习的主要研究内容
数据集/样本集
- 数据集中的每一条记录称为样本,样本由属性和标记组成
- 对有标记的数据集的学习叫做监督学习,监督学习的过程就是对数据的学习。总结出属性/标记之间的映射关系,即为模型。
- 模型一般称为假设或学习器,通常用一个估计函数来表示,学习到的模型应该逼近真实存在的规律。这个真实存在的规律称为
ground truth
,我们将其称为真实
监督学习:回归与分类
无监督学习:在样本数据没有标记的情况下,挖掘出数据内部蕴含的关系。如聚类
- 聚类:把相似度高的样本聚合在一起,物以类聚、人以群分
- 距离:描述了特征值之间的相似度
半监督学习
- 将有监督学习和无监督学习相结合
- 综合使用大量的没有标记数据和少量有标记的数据共同进行学习
一元线性回归:在给定的已知点的基础上,预测出更精准的直线
y=wx+b
模型变量:x;模型参数 w:权重;b:偏置值
如何由给定的样本x和y的值确定模型参数w和b的值
- 样本:
- 拟合误差/残差:样本点到直线的竖直距离
- 估计值:
最佳拟合直线应该使得所有点的残差累计值最小 - 残差和最小
- 残差绝对值和最小
- 残差平方和最小平方损失函数,均方差损失函数
其他损失函数的两个性质
- 非负性:保证样本误差不会相互抵消
- 一致性:损失函数的值和误差变化一致单调有界并收敛于0
最小二乘法
- 已知:
- 未知:
w,b取何值时,Loss取值最小求极值问题:极值点的偏导数为零
梯度下降法
- 解析解根据严格的推导和计算得到,是方程的精确解,可以在任意精度下满足方程
- 数值解通过某种近似计算得到的解,能够在给定的精度下满足方程
- 一元凸函数求极值
步长太小,迭代次数多,收敛慢
步长太大,引起震荡,可能无法收敛
使用斜率去调节步长 - 二元凸函数迭代算法
对于机器学习算法,只要能够把损失函数描述成凸函数,就一定可以采用梯度下降法,以最快的速度更新权值向量w,找出使损失函数达到最小值点的位置
- 自动调节步长
- 自动确定下一次更新的方向
- 保证收敛性
使用梯度下降法求解一元线性回归问题
- 编程中损失函数经常使用均方差损失函数
- 模型参数更新算法
详细步骤
- 加在样本数据
- 设置超参数学习率、迭代次数
- 设置模型参数初值
- 训练模型
- 结果可视化
import numpy as np
import matplotlib.pyplot as plt
x=np.array([137.97,104.50,100.00,124.32,79.20,99.00,124.00,114.00,106.90,138.05,53.75,46.91,68.00,63.02,81.26,86.21])
y=np.array([145.00,110.00,93.00,116.00,65.32,104.00,118.00,91.00,62.00,133.00,51.00,45.00,78.50,69.65,75.69,95.30])
learn_rate=0.00001 #学习率
iter=100 #迭代次数
display_step=10
np.random.seed(612)
# 设置w,b的初始值
w=np.random.randn()
b=np.random.randn()
# 训练模型
mse=[]
for i in range(0,iter+1):
dL_dw=np.mean(x*(w*x+b-y))
dL_db=np.mean(w*x+b-y)
w=w-learn_rate*dL_dw
b=b-learn_rate*dL_db
pred=w*x+b
Loss=np.mean(np.square(y-pred))/2
mse.append(Loss)
if(i%display_step==0):
print("i:%i,Loss:%f,w:%f,b:%f" % (i,mse[i],w,b))
i:0,Loss:3874.109891,w:0.082574,b:-1.161967
i:10,Loss:562.192567,w:0.648530,b:-1.156447
i:20,Loss:148.653167,w:0.848517,b:-1.154463
i:30,Loss:97.016943,w:0.919184,b:-1.153729
i:40,Loss:90.569412,w:0.944155,b:-1.153436
i:50,Loss:89.764324,w:0.952978,b:-1.153299
i:60,Loss:89.663774,w:0.956096,b:-1.153217
i:70,Loss:89.651196,w:0.957197,b:-1.153155
i:80,Loss:89.649602,w:0.957586,b:-1.153099
i:90,Loss:89.649380,w:0.957723,b:-1.153046
i:100,Loss:89.649329,w:0.957771,b:-1.152994
plt.rcParams['font.sans-serif']=['SimHei']
plt.figure()
plt.scatter(x,y,color='red',label="销售记录")
plt.scatter(x,pred,color="blue")
plt.plot(x,pred,color="blue",label="梯度下降法")
plt.plot(x,0.89*x+5.41,color="green",label="解析法")
plt.xlabel("Area",fontsize=14)
plt.ylabel("Price",fontsize=14)
plt.legend(loc="upper left")
plt.show()
output_2_0.png
梯度下降法求解多元线性回归
- 需要对数据进行归一化/标准化:将数据的值限制在一定的范围之内使所有属性处于同一范围、同一数量级下,更快收敛到最优解,提高学习器的精度
- 归一化分类线性归一化、标准差归一化、非线性映射归一化
- 线性归一化、标准差归一化、非线性映射归一化:对原始数据的非线性变换指数、对数、正切
梯度下降法步骤
- 确定损失函数
- 损失函数求导数计算梯度
- 更新模型参数
tensorflow提供了强大的自动求导机制
Variable对象
- 对tensor对象的进一步封装
- 在模型训练过程中自动记录梯度信息,由算法自动优化
- 可以被训练的变量
- 在机器学习中可以作为模型参数
tf.Variable(initial_value,dtype)
- 将张量封装为可训练变量
import tensorflow as tf
tf.Variable(3)
<tf.Variable 'Variable:0' shape=() dtype=int32, numpy=3>
x=tf.Variable(tf.constant([[1,2],[3,4]]))
x[0]
<tf.Tensor: shape=(2,), dtype=int32, numpy=array([1, 2])>
type(x[0])
tensorflow.python.framework.ops.EagerTensor
tensorflow自动求导机制--G'radientTape
with GrandientTape() as tape:
函数表达式
grad=tape.gradient(函数,自变量)
- 多元函数求偏导
tape.gradient(函数,自变量)
x=tf.Variable(3.)
with tf.GradientTape() as tape:
y=x*x
dy_dx=tape.gradient(y,x)
y,dy_dx
(<tf.Tensor: shape=(), dtype=float32, numpy=9.0>,
<tf.Tensor: shape=(), dtype=float32, numpy=6.0>)
tensorflow实现梯度下降法
- 导入需要的库
- 加载数据样本
- 设置超参数
- 设置模型参数初始值
- 训练模型
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
x=np.array([137.97,104.50,100.00,124.32,79.20,99.00,124.00,114.00,106.90,138.05,53.75,46.91,68.00,63.02,81.26,86.21])
y=np.array([145.00,110.00,93.00,116.00,65.32,104.00,118.00,91.00,62.00,133.00,51.00,45.00,78.50,69.65,75.69,95.30])
learn_rate=0.0001 #学习率
iter=100 #迭代次数
display_step=10
np.random.seed(612)
# 设置w,b的初始值
np.random.seed(612)
w=tf.Variable(np.random.randn())
b=tf.Variable(np.random.randn())
# 训练模型
mse=[]
for i in range(0,iter+1):
with tf.GradientTape() as tape:
pred=w*x+b
Loss=0.5*tf.reduce_mean(tf.square(y-pred))
mse.append(Loss)
dL_dw,dL_db=tape.gradient(Loss,[w,b])
w.assign_sub(learn_rate*dL_dw)
b.assign_sub(learn_rate*dL_db)
if(i%display_step==0):
print("i:%i,Loss:%f,w:%f,b:%f" % (i,mse[i],w,b))
i:0,Loss:4749.374023,w:0.946134,b:-1.153577
i:10,Loss:89.649315,w:0.957797,b:-1.152948
i:20,Loss:89.649063,w:0.957792,b:-1.152432
i:30,Loss:89.648788,w:0.957787,b:-1.151916
i:40,Loss:89.648529,w:0.957782,b:-1.151399
i:50,Loss:89.648277,w:0.957777,b:-1.150883
i:60,Loss:89.647995,w:0.957772,b:-1.150367
i:70,Loss:89.647720,w:0.957767,b:-1.149851
i:80,Loss:89.647469,w:0.957762,b:-1.149335
i:90,Loss:89.647194,w:0.957757,b:-1.148818
i:100,Loss:89.646942,w:0.957752,b:-1.148302
模型评估
- 误差:学习器的预测输出和样本的真实标记之间的差异
- 训练误差:训练集上的误差
- 泛化误差:在新样本上的误差
- 过拟合:学习过度,在训练集上表现很好,在新样本上泛化误差很大
- 欠拟合:学习不足,没有学习到样本中的通用的特征
机器学习的目标:泛化误差小
训练集和测试集
- 训练集:训练模型
- 测试集:测试学习器在新样本上的预测或判断能力
- 测试误差:用来近似泛化误差
网友评论