线性回归梯度下降法python实现


线性回归的公式
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=1m(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=1m(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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coderzjy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值