小批量梯度下降的代码实现

作为线性回归中理论上最佳的梯度下降代码实现,我测试了一下结果,确实和理论结果一样,同迭代次数下小批量梯度下降效果没有批量梯度下降的效果好,但是增加迭代次数后就基本持平了。所以小批量梯度下降应该是线性回归中大中小量级数据最佳的算法。

代码实现如下:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import joblib

# 导入数据
path = 'ex1data1.txt'
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])

# 分离特征和目标变量
X = data.iloc[:, 0:1].values  # Population列
y = data.iloc[:, 1].values  # Profit列
m = len(y)  # 样本数量

# 添加一列全为1的截距项
X = np.append(np.ones((m, 1)), X, axis=1)

# 批量梯度下降参数
alpha = 0.01  # 学习率
iterations = 3000  # 迭代次数

def miniBatchGradientDescent(X, y, theta, alpha, num_iters, batch_size):
    m = len(y)  # 获取样本数量
    cost_history = []  # 初始化损失历史列表

    for iter in range(num_iters):  # 对于每次迭代
        cost = 0  # 初始化本次迭代的总成本
        indices = np.random.permutation(m)  # 随机打乱样本的索引
        X_shuffled = X[indices]  # 根据打乱的索引重新排列X
        y_shuffled = y[indices]  # 根据打乱的索引重新排列y

        for i in range(0, m, batch_size):  # 将数据分成多个批次进行迭代
            X_i = X_shuffled[i:i+batch_size]  # 获取当前批次的X
            y_i = y_shuffled[i:i+batch_size]  # 获取当前批次的y

            prediction = np.dot(X_i, theta)  # 计算当前批次的预测值
            error = prediction - y_i  # 计算误差

            theta = theta - (alpha / batch_size) * np.dot(X_i.T, error)  # 更新参数
            cost += computeCost(X_i, y_i, theta)  # 计算并累加当前批次的成本

        cost_history.append(cost / (m // batch_size))  # 计算并记录本次迭代的平均成本

    return theta, cost_history  # 返回最终参数和成本历史记录

# 初始化模型参数
theta = np.zeros(2)  # 注意这里theta的长度是2
# 定义批次大小
batch_size = 32  # 例如,32


"""
下降前的损失显示
"""
# 定义损失函数,用于显示调用前后的损失值对比
def computeCost(X, y, theta):
    m = len(y)
    predictions = X.dot(theta)
    square_err = (predictions - y) ** 2
    return np.sum(square_err) / (2 * m)
# 计算初始损失
initial_cost = computeCost(X, y, theta)
print("初始的损失值:", initial_cost)

# 使用小批量梯度下降进行模型拟合
theta, cost_history = miniBatchGradientDescent(X, y, theta, alpha, iterations, batch_size)

"""
下降后的损失显示
"""
# 计算优化后的损失
final_cost = computeCost(X, y, theta)
print("下优化后的损失值:", final_cost)

"""
使用需要预测的数据X进行预测
"""
# 假设的人口数据
population_values = [3.5, 7.0]  # 代表35,000和70,000人口

# 对每个人口值进行预测
for pop in population_values:
    # 将人口值转换为与训练数据相同的格式(包括截距项)
    predict_data = np.matrix([1, pop])  # 添加截距项

    # 使用模型进行预测
    predict_profit = np.dot(predict_data, theta.T)
    print(f"模型预测结果 {pop} : {predict_profit[0,0]}")
"""
使用模型绘制函数
"""
# 创建预测函数
x_values = np.array(X[:, 1])
f = theta[0] * np.ones_like(x_values) + (theta[1] * x_values)  # 使用广播机制


# 绘制图表
fig, ax = plt.subplots(figsize=(12, 8))
ax.plot(x_values, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profit, label='Training Data')
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()

"""
保存模型
"""
# 保存模型
joblib.dump(theta, 'linear_regression_model.pkl')

"""
加载模型并执行预测
"""
# 加载模型
loaded_model = joblib.load('linear_regression_model.pkl')

# 假设的人口数据
population_values = [3.5, 7.0]  # 代表35,000和70,000人口

# 使用模型进行预测
for pop in population_values:
    # 更新预测数据矩阵,包括当前的人口值
    predict_data = np.matrix([1, pop])
    
    # 进行预测
    predict_value = np.dot(predict_data, loaded_model.T)
    print(f"模型预测结果 {pop} : {predict_value[0,0]}")

3000次迭代的运行后结果:

初始的损失值: 32.072733877455676
下优化后的损失值: 4.486033043082418(会波动) 对比批量梯度下降:4.47802760987997 非常接近了
模型预测结果 3.5 : 0.32861314903187555
模型预测结果 7.0 : 4.558305776819226
模型预测结果 3.5 : 0.32861314903187555
模型预测结果 7.0 : 4.558305776819226

总结:线性回归问题中小批量梯度下降应该是通用的算法了。

注:本文为学习吴恩达版本机器学习教程的代码整理,使用的数据集为https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes/blob/f2757f85b99a2b800f4c2e3e9ea967d9e17dfbd8/code/ex1-linear%20regression/ex1data1.txt

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值