线性回归的公式:
h
θ
(
x
)
=
θ
0
+
θ
1
x
1
+
θ
2
x
2
+
⋯
+
θ
n
x
n
h_\theta(x) = \theta_0 + \theta_1 x_1 + \theta_2 x_2 + \dots + \theta_n x_n
hθ(x)=θ0+θ1x1+θ2x2+⋯+θnxn
其中,
h
θ
(
x
)
h_\theta(x)
hθ(x) 是预测值,
θ
\theta
θ 是模型参数,
x
1
,
x
2
,
…
,
x
n
x_1, x_2, \dots, x_n
x1,x2,…,xn 是输入特征。
梯度下降的更新公式:
θ
j
=
θ
j
−
α
⋅
1
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
x
j
(
i
)
\theta_j = \theta_j - \alpha \cdot \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)
其中,
θ
j
\theta_j
θj 是第
j
j
j 个参数,
α
\alpha
α 是学习率,
m
m
m 是样本的数量,
h
θ
(
x
(
i
)
)
h_\theta(x^{(i)})
hθ(x(i)) 是预测值,
y
(
i
)
y^{(i)}
y(i) 是实际值,
x
j
(
i
)
x_j^{(i)}
xj(i) 是样本的第
j
j
j 个特征。
线性回归的损失函数(均方误差):
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
其中:
- J ( θ ) J(\theta) J(θ) 是损失函数(成本函数),
- m m m 是样本的数量,
- h θ ( x ( i ) ) h_\theta(x^{(i)}) hθ(x(i)) 是模型对第 i i i 个样本的预测值,
- y ( i ) y^{(i)} y(i) 是第 i i i 个样本的实际值。
通常,在梯度下降中,我们通过最小化损失函数来优化模型参数
θ
\theta
θ。
X矩阵的每一行代表一组数据,每一列代表一个特征
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
def computeCost(X,y,theta):
m = X.shape[0]
part = np.power(((X@theta.T)-y),2)
return np.sum(part)/(m*2)
def gradientDescent(X,y,theta,alpha,iterations):
#副本
temp = theta
#样本数量
m = X.shape[0]
#特征数
params = theta.shape[1]
#记录每一次的成本变化
costs = np.zeros(iterations)
#迭代iterations次
for i in range(iterations):
error = X@theta.T-y
for j in range(params):
temp[0,j] = temp[0,j] - (alpha/m)*np.sum(np.multiply(error,X[:,j:j+1]))
theta = temp
costs[i] = computeCost(X,y,theta)
return theta, costs
# 读取数据,dataframe
data = pd.read_csv('ex1data1.txt', header=None,names = ["population","profits"])
#插入一行1,作为线性回归函数的常数项
data.insert(0,"Ones",1)
print(data.head())
cols = data.shape[1]
#切片第二项也要用:,保持是dataframe
X = data.iloc[:,0:cols-1]
y = data.iloc[:,cols-1:cols]
#theta都初始化为0,np.array默认是行向量
theta = np.zeros((1,cols-1))
#将dataframe转化为np.array
X = X.to_numpy()
y = y.to_numpy()
print(X.shape)
print(y.shape)
print(theta.shape)
alpha = 0.01
iterations = 1000
theta, costs =gradientDescent(X,y,theta,alpha,iterations)
print(costs[iterations-1])
x = np.linspace(data.population.min(), data.population.max(),100)
f = theta[0,0] + theta[0,1] * x
fig = plt.figure()
#fig 为整个画图区域,ax为子图的集合
#当nrows=1或ncols=1时为一维数组,此时下标索引只有一个维度,否则是两个维度
fig,ax = plt.subplots(figsize=(12,8),nrows=1,ncols=2)
ax[0].plot(x, f, 'r', label='Prediction')
ax[0].set_title('Predicted Profit vs. Population Size')
ax[0].set_xlabel('population')
ax[0].set_ylabel('profit')
ax[0].scatter(data.population, data.profits, label='Traning Data')
ax[0].legend()
#np.arange(iterations) 的意思是 生成从 0 到 iterations-1 的整数数组。
#np.arange(start, stop, step, dtype) 用于生成等间隔的数组
ax[1].plot(np.arange(iterations),costs,label='Cost Function')
ax[1].set_title('Error vs. Training Epoch')
ax[1].set_xlabel('iterations')
ax[1].set_ylabel('cost')
ax[1].legend()
plt.show()
使用scikit-learn进行线性回归
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn import linear_model
# 1. 加载数据并添加截距列
data = pd.read_csv('ex1data1.txt', header=None, names=["Population", "Profit"])
data.insert(0, "Ones", 1)
# 2. 提取特征矩阵 X 和目标变量 y
cols = data.shape[1]
X = data.iloc[:, 0:cols-1].values # 直接转换为 NumPy 数组
y = data.iloc[:, cols-1].values # 目标变量为一维数组
# 3. 训练线性回归模型
model = linear_model.LinearRegression()
model.fit(X, y)
# 4. 生成用于绘制回归线的数据点
# 注意:X 需要包含截距列 "Ones"(值为1)和 "Population" 特征
x_plot = np.linspace(data.Population.min(), data.Population.max(), 100)
X_plot = np.c_[np.ones_like(x_plot), x_plot] # 添加截距列
# 5. 预测并获取结果
f = model.predict(X_plot)
# 6. 绘图
plt.figure(figsize=(12, 8))
plt.plot(x_plot, f, 'r', label='Regression Line')
plt.scatter(data.Population, data.Profit, label='Training Data')
plt.xlabel('Population')
plt.ylabel('Profit')
plt.title('Predicted Profit vs. Population Size')
plt.legend()
plt.show()