版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/irving512/article/details/72628416
0. 参考资料
- Coursera ML Week1/Week2。
- 周志华《机器学习》第三章。
- 本文Github链接
1. 总体介绍
1.1. 回归(Regression)
如果需要预测的值是连续值(如价格),则称此类学习任务为“回归”(Regression)。
1.2. 线性模型(Linear Model):
- 概念:试图学得一个通过属性的线性组合来进行预测的函数。
- 基本结构,其中
x1⋯xn 为输入属性,θ0⋯θn 为需要计算的参数:
h(x)=θ1x1+θ2x2+...+θnxn+b - 为了方便编程,将
b 转换为θ0 ,并定义x0=1 ,则有以下公式:
hθ(x)=θ0x0+θ1x1+θ2x2+...+θnxn - 矩阵形式:
X=⎡⎣⎢⎢⎢⎢x0x1⋮xn⎤⎦⎥⎥⎥⎥θ=⎡⎣⎢⎢⎢⎢θ0θ1⋮θn⎤⎦⎥⎥⎥⎥hθ(x)=θTX
2. 损失函数(Loss Function)
2.1. 概念
用来估计预期结果
真实值
2.2. 平方损失函数
在实际应用中,常用均方差作为损失函数(假设一共有m个样本,其中分母中添加2
是为了计算方便):
2.3. 作用
如前所述,损失函数用于估计预测结果
与真实值
之间的偏差。为了优化模型,必须调整参数
3. 梯度下降算法(Gradient descent)
3.1. 概念
- 梯度下降(Gradient Descent),又名最速下降法,是最优化算法(Optimization Arithmetic)中的一种。
- 优化算法的目标是取最优值。
- 线性回归中,梯度下降的目标是:取
θ0⋯θn 的最优值,令J(θ) 取值最小。
3.2. 原理
- 利用偏导数计算损失函数的梯度,利用负梯度方向作为搜索方向,接近目标值。
- 若损失函数为凸函数,利用该方法可以获取全局最优解。
- 若损失函数是一般函数,根据初始位置不同,可能会计算得到不同的局部最优解(不一定是全局最优解)。
3.3. 计算方法
- 一般形式如下:
θi:=θi−α∂∂θiJ(θ) - 对于平方损失函数如下:
θi := θi−α1m∑j=1m(hθ(x(j))−y(j))⋅x(j)i
3.4. 学习率(Learning Rate)
- 控制每一次梯度下降,修改的
θ 值。 - 技巧:
- 画出损失函数
J(θ) 与迭代次数之间的图像。 - 当学习率过大时,可能不会收敛。
- 当学习速率过低,收敛速度太慢。
- 合适的学习率:损失函数随着时间变化逐渐降低,且下降速度不慢。
- 画出损失函数
3.5. 特征标准化(Feature Normalization)
- 概念:标准化数据特征范围(即不同输入数据都在同一数量级上)。
- 使用特征标准化的原因:如果一个特征的范围更大,则该特征对于损失函数的影响也更大。为了使所有特征对于损失函数的影响都差不多,则应该使用特征缩放。
- 常用特征标准化方法:
- 特征缩放(feature scaling),将数据的特征缩放到[0,1]之间:
x′=x−min(x)max(x)−min(x) - 均值标准化(mean normalization),其中
μ 为均值,σ 为标准差:
x′=x−μσ
- 特征缩放(feature scaling),将数据的特征缩放到[0,1]之间:
4. 编程实现
4.1. 原始数据
- 数据源:Coursra ML Week2编程作业提供的数据。
- 输入特征与结果矩阵,每一行代表一个样本以及对应结果:
[Xy]=⎡⎣⎢⎢⎢⎢⎢(x(1))Ty(1)(x(2))Ty(2)⋮(x(m))Ty(m)⎤⎦⎥⎥⎥⎥⎥ - 其中每个样本(不包括
x(i)0 )有
x(i)=⎡⎣⎢⎢⎢⎢⎢⎢x(i)1x(i)2⋮x(i)n⎤⎦⎥⎥⎥⎥⎥⎥
4.2. 数据预处理
获取特征矩阵(
m*(n+1)
维矩阵)与结果矩阵(m*1
维矩阵)
X=⎡⎣⎢⎢⎢⎢⎢(x(1))T(x(2))T⋮(x(m))T⎤⎦⎥⎥⎥⎥⎥y=⎡⎣⎢⎢⎢⎢⎢y(1)y(2)⋮y(m)⎤⎦⎥⎥⎥⎥⎥
其中,每个样本(包括
x(i)0=1 ,(n+1)*1
维矩阵)为
x(i)=⎡⎣⎢⎢⎢⎢⎢⎢x(i)0x(i)1⋮x(i)n⎤⎦⎥⎥⎥⎥⎥⎥ 特征标准化
4.3. 计算损失函数值与梯度下降值(optional)
- 如果使用TensorFlow实现,有库函数可以调用。
- 为了加强记忆,理解具体实现,自己推导出以下公式。
- 损失函数
J
为实数。
J=12m(Xθ−y)T(Xθ−y) - 参数变化量
grad
为n+1
维向量,表示θi 的变化量。
grad=XT(Xθ−y)
- 损失函数
5. TensorFlow实现
5.1. TensorFlow代码
import tensorflow as tf
import numpy as np
def read_data(file_name, delimiter=','):
return np.loadtxt(file_name, delimiter=delimiter)
# 将4.1节原始数据,转换为4.2节中数据
def init_data(input_data):
input_x = input_data[:, 0:-1]
input_y = input_data[:, -1].reshape(m, 1)
input_x = np.column_stack((np.ones(input_data.shape[0]), input_x)).reshape(m, n)
return input_x, input_y
# 对应3.5节中,均值标准化
def feature_normalization(input_x):
for i in range(1, input_x.shape[1]):
mn = np.mean(input_x[:, i], dtype=np.float64)
std = np.std(input_x[:, i], ddof=1, dtype=np.float64)
input_x[:, i] = (input_x[:, i] - mn)/std
return input_x
# 实现线性回归模型
def tensor_flow_run(input_x, input_y):
# 初始化placeholder,后续将特征矩阵与结果向量导入
X = tf.placeholder("float64")
Y = tf.placeholder("float64")
# 初始化theta
theta = tf.Variable(tf.zeros([n, 1], dtype=tf.float64))
# 构建cost函数,即2.2节公式
cost = tf.reduce_sum(tf.square(tf.matmul(X, theta) - Y)) / 2 / m
# 初始化梯度下降算法的学习率与策略
train_op = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(cost)
with tf.Session() as sess:
# 初始化所有参数
init = tf.global_variables_initializer()
sess.run(init)
# 进行梯度下降
for i in range(ITERATIONS):
# 导入特征矩阵与结果向量,进行一次梯度下降计算
# 调用TensorFlow库函数,实现4.3节内容
sess.run(train_op, feed_dict={X: input_x, Y: input_y})
# 输出最终theta参数
print(sess.run(theta))
# 初始化学习率与迭代次数
LEARNING_RATE = 0.01
ITERATIONS = 1000
# 输入数据
data = read_data('ex1data1.txt', ',')
# 计算参数数量以及样本数量
m = data.shape[0]
n = data.shape[1]
# 对输入数据进行处理
datas = init_data(data)
x = datas[0]
y = datas[1]
# 特征标准化(均值标准化)
x = feature_normalization(x)
# 使用TensorFlow实现线性回归模型的梯度下降
tensor_flow_run(x, y)
5.2. 运行结果
- 数据源介绍:Coursera Machine Learning中,第二周课程数据。
- 测试1:
- 输入数据:学习率0.01,梯度下降1000次,输入文件为
ex1data1.txt
。 - 输出(官方结果):
[-3.6303 1.1664]
。
- 输入数据:学习率0.01,梯度下降1000次,输入文件为
- 测试2:
- 学习数据:学习率0.001,梯度下降400次,输入文件
ex1data2.txt
。 - 输出(非官方结果):
[112272.892901 33056.237507 14493.332476]
。
- 学习数据:学习率0.001,梯度下降400次,输入文件