parent
7383f80a5e
commit
dca38ee263
@ -0,0 +1,117 @@
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# 设置中文显示
|
||||
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
|
||||
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
|
||||
|
||||
# 生成数据集
|
||||
def gen():
|
||||
m = 20
|
||||
X0 = np.ones((m, 1))
|
||||
X1 = np.arange(1, m+1).reshape(m, 1)
|
||||
X = np.hstack((X0, X1))
|
||||
true_params = np.array([[1], [1.5]])
|
||||
y = np.dot(X, true_params) + np.random.normal(0, 2, size=(m, 1))
|
||||
return X, X1, y, m
|
||||
|
||||
# 定义代价函数 (均方误差)
|
||||
def cos(theta, X, y, m):
|
||||
error = np.dot(X, theta) - y
|
||||
return (1 / (2 * m)) * np.dot(error.T, error)[0, 0]
|
||||
|
||||
# 定义梯度函数
|
||||
def gra(theta, X, y, m):
|
||||
error = np.dot(X, theta) - y
|
||||
return (1 / m) * np.dot(X.T, error)
|
||||
|
||||
# 梯度下降迭代
|
||||
def des(X, y, m, al=0.01, max=10000, t=1e-5):
|
||||
"""
|
||||
使用梯度下降算法求解最优参数
|
||||
|
||||
参数:
|
||||
X: 特征矩阵
|
||||
y: 目标值向量
|
||||
m: 样本数量
|
||||
al: 学习率
|
||||
max: 最大迭代次数
|
||||
t: 收敛阈值
|
||||
|
||||
返回:
|
||||
theta: 最优参数
|
||||
costs: 每次迭代的代价函数值
|
||||
"""
|
||||
theta = np.array([[1], [1]]) # 初始化参数 [b, w]
|
||||
costs = [] # 记录每次迭代的代价函数值
|
||||
|
||||
for iteration in range(max):
|
||||
gradient = gra(theta, X, y, m)
|
||||
theta = theta - al * gradient
|
||||
cost = cos(theta, X, y, m)
|
||||
costs.append(cost)
|
||||
|
||||
# 检查收敛条件
|
||||
if np.max(np.abs(gradient)) < t:
|
||||
print(f"在第 {iteration+1} 次迭代后收敛")
|
||||
break
|
||||
|
||||
# 每100次迭代打印一次信息
|
||||
if (iteration + 1) % 100 == 0:
|
||||
print(f"迭代 {iteration+1}/{max}, 代价: {cost:.6f}")
|
||||
|
||||
return theta, costs
|
||||
|
||||
# 绘制结果
|
||||
def res(X1, y, theta, costs=None):
|
||||
plt.figure(figsize=(14, 5))
|
||||
|
||||
# 绘制数据点和拟合直线
|
||||
plt.subplot(1, 2, 1)
|
||||
plt.scatter(X1, y, s=30, c="red", marker="s", label="数据点")
|
||||
plt.xlabel("X")
|
||||
plt.ylabel("Y")
|
||||
plt.title("数据点与拟合直线")
|
||||
|
||||
x_range = np.arange(0, 21, 0.2)
|
||||
y_pred = theta[0] + theta[1] * x_range
|
||||
plt.plot(x_range, y_pred, 'b-', label=f'拟合直线: y = {theta[0][0]:.4f} + {theta[1][0]:.4f}x')
|
||||
plt.legend()
|
||||
|
||||
# 如果提供了代价函数值,绘制代价函数变化曲线
|
||||
if costs is not None:
|
||||
plt.subplot(1, 2, 2)
|
||||
plt.plot(range(1, len(costs) + 1), costs, 'g-')
|
||||
plt.xlabel("迭代次数")
|
||||
plt.ylabel("代价函数值")
|
||||
plt.title("代价函数收敛过程")
|
||||
plt.grid(True)
|
||||
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
|
||||
# 主函数
|
||||
def main():
|
||||
# 生成数据集
|
||||
X, X1, y, m = gen()
|
||||
|
||||
# 设置超参数
|
||||
al = 0.01 # 学习率
|
||||
max = 10000 # 最大迭代次数
|
||||
t = 1e-5 # 收敛阈值
|
||||
|
||||
# 执行梯度下降
|
||||
print("开始执行梯度下降算法...")
|
||||
theta, costs = des(X, y, m, al, max, t)
|
||||
|
||||
# 输出结果
|
||||
print("\n优化结果:")
|
||||
print(f"截距项 b = {theta[0][0]:.6f}")
|
||||
print(f"斜率项 w = {theta[1][0]:.6f}")
|
||||
print(f"最终代价函数值 = {cos(theta, X, y, m):.6f}")
|
||||
|
||||
# 绘制结果
|
||||
res(X1, y, theta, costs)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in new issue