线性回归三种实现方式
1.梯度下降
梯度下降是一种迭代优化算法,用于寻找函数的最小值。其核心思想是沿着梯度的反方向(即函数值下降最快的方向)逐步更新模型参数,直到收敛到最小值。
线性回归的代价函数定义为:
J
(
θ
)
=
1
2
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} (h_{\theta}(x^{(i)}) - y^{(i)})^2
J(θ)=2m1i=1∑m(hθ(x(i))−y(i))2
梯度下降需要选择学习速率
α
\alpha
α并进行多次迭代
2.sklearn 中的LinearRegression 类
LinearRegression 类默认使用正规方程来最小化代价函数。sklearn 的 LinearRegression 使用 numpy.linalg.lstsq 函数来求解线性最小二乘问题,这本质上是通过正规方程来计算最优解。
3.正规方程
正规方程是通过解析方法直接求解代价函数的最小值,即通过求导找到使代价函数最小的参数值。对于线性回归问题,正规方程的解可以通过矩阵运算直接得到。
正规方程的求解:
θ
=
(
X
T
X
)
−
1
X
T
y
\theta = (X^T X)^{-1} X^T y
θ=(XTX)−1XTy
正规方程公式用于直接求解线性回归模型的参数,而无需进行迭代优化。
一、ML-Exercise1_ex1data1_(1)BGD.py代码实现(自定义函数)
(1) 代价函数 computeCost(X, y, theta)
数学公式:
J
(
θ
)
=
1
2
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
J(\theta) = \frac{1}{2m} \sum_{i=1}^m \left( h_\theta(x^{(i)}) - y^{(i)} \right)^2
J(θ)=2m1i=1∑m(hθ(x(i))−y(i))2
代码实现:
def computeCost(X, y, theta):
inner = np.power(((X * theta.T) - y), 2)
return np.sum(inner) / (2 * len(X))
(2)批量梯度下降 gradientDescent(X, y, theta, alpha, iters)
数学公式:
θ
j
:
=
θ
j
−
α
1
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
x
j
(
i
)
\theta_j := \theta_j - \alpha \frac{1}{m} \sum_{i=1}^{m} \left( h_\theta(x^{(i)}) - y^{(i)} \right) x_j^{(i)}
θj:=θj−αm1i=1∑m(hθ(x(i))−y(i))xj(i)
代码实现:
for j in range(parameters):
term = np.multiply(error, X[:,j]) # (hθ(x) - y) * x_j
temp[0,j] = theta[0,j] - ((alpha / len(X)) * np.sum(term))
代码实现
1. 导入库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
导入了三个常用的库:
numpy
:用于数值计算。pandas
:用于数据处理。matplotlib.pyplot
:用于绘图。
2 定义代价函数
def computeCost(X, y, theta):
inner = np.power(((X * theta.T) - y), 2)
return np.sum(inner) / (2 * len(X))
代价函数用于衡量模型预测值和实际值之间的差异。公式如下:
J ( θ ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} (h_{\theta}(x^{(i)}) - y^{(i)})^2 J(θ)=2m1i=1∑m(hθ(x(i))−y(i))2
- X X X:特征矩阵。
- y y y:目标变量向量。
- θ \theta θ:模型参数。
- m m m:样本数量。
3. 定义批量梯度下降函数
def gradientDescent(X, y, theta, alpha, iters):
temp = np.matrix(np.zeros(theta.shape)) # 初始化临时参数矩阵
parameters = int(theta.ravel().shape[1]) # 获取参数数量
cost = np.zeros(iters) # 初始化成本存储数组
for i in range(iters):
error = (X * theta.T) - y # 计算误差
for j in range(parameters):
term = np.multiply(error, X[:,j]) # 计算梯度项
temp[0,j] = theta[0,j] - ((alpha / len(X)) * np.sum(term)) # 更新参数
theta = temp # 更新参数
cost[i] = computeCost(X, y, theta) # 计算并存储当前成本
return theta, cost
梯度下降算法用于最小化代价函数。其更新规则如下:
θ j : = θ j − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) \theta_j := \theta_j - \alpha \frac{1}{m} \sum_{i=1}^{m} (h_{\theta}(x^{(i)}) - y^{(i)}) x_j^{(i)} θj:=θj−αm1i=1∑m(hθ(x(i))−y(i))xj(i)
- α \alpha α:学习速率。
- m m m:样本数量。
- x j ( i ) x_j^{(i)} xj(i):第 i i i 个样本的第 j j j 个特征。
4. 数据准备
path = 'ex1data1.txt'
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])
读取数据文件并存储为 pandas
的 DataFrame
对象。
5. 数据可视化
data.plot(kind='scatter', x='Population', y='Profit', figsize=(12,8))
plt.show()
绘制散点图,展示人口与利润之间的关系。
6. 添加一列 1 的特征
data.insert(0, 'Ones', 1)
为了方便线性回归计算,在数据框的第一列插入全为 1 的列,用于线性回归中的截距项。
7. 初始化变量
cols = data.shape[1]
X = data.iloc[:,0:cols-1] # 特征矩阵
y = data.iloc[:,cols-1:cols] # 目标变量向量
初始化特征矩阵 X X X 和目标变量向量 y y y。
8. 转换为 NumPy 矩阵
X = np.matrix(X.values)
y = np.matrix(y.values)
theta = np.matrix(np.array([0,0]))
将 pandas
的 DataFrame
对象转换为 NumPy
矩阵,初始化参数
θ
\theta
θ。
9. 检查维度
print(X.shape, theta.shape, y.shape)
# 输出:(97, 2) (1, 2) (97, 1)
输出各矩阵的形状,确保维度正确。
10. 计算初始代价函数值
computeCost(X, y, theta)
计算初始参数 θ \theta θ 下的代价函数值。
11. 设置超参数
alpha = 0.01
iters = 10000
设置学习速率 α \alpha α 和迭代次数 i t e r s iters iters。
12. 运行梯度下降算法
bestTheta, cost = gradientDescent(X, y, theta, alpha, iters)
运行梯度下降算法,找到最佳参数 θ \theta θ 和每次迭代的成本值。
13. 输出最佳参数
print('梯度下降算法的预测 theta = ', bestTheta)
打印最佳参数 θ \theta θ。
14. 计算最终的代价函数值
computeCost(X, y, bestTheta)
计算最终最佳参数 θ \theta θ 下的代价函数值。
15. 绘制线性回归模型
x = np.linspace(data.Population.min(), data.Population.max(), 100)
f = bestTheta[0, 0] + (bestTheta[0, 1] * x)
fig, ax = plt.subplots(figsize=(12,8))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profit, label='Traning Data')
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()
绘制回归直线和原始数据的散点图。
)
ax.plot(np.arange(iters), cost, 'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()
绘制代价函数值随迭代次数的变化曲线。
17. 预测
predict1 = bestTheta[0, 0] + (bestTheta[0, 1] * 3.5)
predict2 = bestTheta[0, 0] + (bestTheta[0, 1] * 7)
print(predict1, predict2)
对人口分别为 3.5 和 7 的地区进行利润预测。
二、ML-Exercise1_ex1data1_(2)sklearn .py代码实现(sklearn 线性回归)
使用 sklearn 库中的线性回归模型,对单变量线性回归问题进行建模和预测。
通过使用 sklearn,可以更简洁地实现线性回归,而无需从头开始实现梯度下降算法。
代码实现
1. 导入库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
导入必要的库:numpy
(数值计算)、pandas
(数据处理)和 matplotlib.pyplot
(绘图)。
2. 数据准备
path = 'ex1data1.txt'
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])
读取数据文件并存储为 pandas 的 DataFrame 对象。header=None
表示文件没有标题行,names
参数用于指定列名。
3. 数据可视化
data.plot(kind='scatter', x='Population', y='Profit', figsize=(12,8))
plt.show()
绘制散点图,展示人口与利润之间的关系。
4. 变量初始化
cols = data.shape[1]
X = data.iloc[:,0:cols-1] # 特征矩阵
y = data.iloc[:,cols-1:cols] # 目标变量向量
初始化特征矩阵 X
和目标变量向量 y
。
5. 数据类型转换
X = np.matrix(X.values)
y = np.matrix(y.values)
将 pandas 的 DataFrame 对象转换为 NumPy 矩阵。
X_array = np.asarray(X)
y_array = np.asarray(y)
将 NumPy 矩阵转换为 NumPy 数组,以满足 scikit-learn 的输入要求。
6. 模型训练
from sklearn import linear_model
model = linear_model.LinearRegression()
model.fit(X_array, y_array)
导入 sklearn 的线性回归模块,创建线性回归模型并进行训练。
7. 模型评估
print('scikit-learn model的预测')
print('截距项:', model.intercept_)
print('系数:', model.coef_)
输出模型的截距项和系数。
8. 模型预测表现
x = np.array(X_array[:,0])
f = model.predict(X_array).flatten()
fig, ax = plt.subplots(figsize=(12,8))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profit, label='Traning Data')
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()
生成预测值并绘制回归直线和原始数据的散点图。
三、ML-Exercise1_ex1data1_(3)Regulation.py(正规方程)
原理
正规方程通过求解下面的方程来找到使得代价函数最小的参数:
θ
=
(
X
T
X
)
−
1
X
T
y
\theta = (X^T X)^{-1} X^T y
θ=(XTX)−1XTy
其中:
- ( X ) 是特征矩阵。
- ( y ) 是目标变量向量。
- ( θ \theta θ)是模型参数向量。
代码实现
# 正规方程
def normalEqn(X, y):
theta = np.linalg.inv(X.T @ X) @ X.T @ y # X.T @ X 等价于 X.T.dot(X)
return theta
final_theta2 = normalEqn(X, y)
print('正规方程方法:final_theta2 =', final_theta2)
正规方程函数:定义 normalEqn
函数,计算最佳参数 theta
。
计算并输出结果:调用 normalEqn
函数,计算并打印最佳参数 theta
。