输入:房子的面积,$ x $
输出:房子的价格,$ y $
import random
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d, Axes3D
plt.rcParams["figure.figsize"] = (8, 6)
# 生成训练数据
x = np.array([random.randint(80, 140) for i in range(10)])
print("房子面积", x)
def random_price(x):
    y = x*random.uniform(2.8, 3.1) + random.randint(20, 23)
    return round(y, 1)
y = np.array([random_price(i) for i in x])
print("房子的价格", y)
# 可视化数据的分布
plt.scatter(x, y)
plt.show()
# 定义线性回归函数
class LinearRegression(object):
    def __init__(self, theta_0=-50, theta_1=-5):
        self.theta_0 = theta_0
        self.theta_1 = theta_1
    
    def __call__(self, x):
        x = self.theta_0 + self.theta_1 * x
        return x
    
    def update(self, theta_0, theta_1):
        self.theta_0 = theta_0
        self.theta_1 = theta_1
        
linear_regression_model = LinearRegression()
plt.scatter(x, y)
plt.plot([80, 140], [linear_regression_model(i) for i in [80, 140]])
plt.show()
# 定义损失函数
def loss_func(y, y_pred):
    loss = np.square(y - y_pred).mean()
    return loss
y_pred = [linear_regression_model(i) for i in x]
print("真实值", y)
print("预测值", y_pred)
loss = loss_func(y, y_pred)
print("mse loss", loss)
随机梯度下降算法:
损失函数 $$ \begin{align*} J(\theta_0, \theta_1) &= \frac{1}{2m} \sum_{i=1}^{m}[(\theta_0 + \theta_1*x_i) - y_i]^2 \end{align*} $$
分别求 $\theta_0, \theta_1$的导数: $$ \begin{align*} \frac{\partial}{\partial \theta_0} J(\theta_0, \theta_1) &= \frac{1}{m} \sum_{i=1}^{m}(\theta_0 + \theta_1*x_i - y_i) \\ \frac{\partial}{\partial \theta_1} J(\theta_0, \theta_1) &= \frac{1}{m} \sum_{i=1}^{m}x_i * (\theta_0 + \theta_1*x_i - y_i) \\ \end{align*} $$
梯度更新 $$ \begin{align*} \theta_i &= \theta_i - lr*\mathrm{d}\theta_i \end{align*} $$
# 可视化lossx
def show_grade(dots=None):
    theta_0 = np.linspace(-100, 100, 100)
    theta_1 = np.linspace(-10, 10, 100)
    z = np.zeros([len(theta_0), len(theta_0)])
    for i in range(len(theta_0)):
        for j in range(len(theta_1)):
            theta_0_ = theta_0[i]
            theta_1_ = theta_1[j]
            model = LinearRegression(theta_0=theta_0_, theta_1=theta_1_)
            y_ = [model(x_) for x_ in x]
            loss_z_ = loss_func(y, y_)
            z[i, j] = loss_z_
            
    theta_0, theta_1 =np.meshgrid(theta_0, theta_1)
    fig = plt.figure(figsize=(8, 6))
    ax = Axes3D(fig)
    ax.plot_surface(theta_0, theta_1, z, cmap='rainbow', alpha=0.5)
    
    
    if dots:
        list_x = dots[0]
        list_y = dots[1]
        # plot
        for i in range(len(list_x)):
            a = list_x[i]
            b = list_y[i]
            
            model = LinearRegression(theta_0=a, theta_1=b)
            y_ = [model(x_) for x_ in x]
            c = loss_func(y, y_)
            ax.scatter(a, b, c, c='Black', s=10, alpha=1, marker='o')
    
    # ax.view_init(elev=30, azim=175)
    plt.xlabel('theta_0', fontsize=16)
    plt.ylabel('theta_1', fontsize=16)
    plt.show()
show_grade()
# 绘当前的梯度
theta_0 = linear_regression_model.theta_0
theta_1 = linear_regression_model.theta_1
    
show_grade(dots=([theta_0], [theta_1]))
# 计算梯度
def cal_dtheta0(model, x, y):
    theta_0 = model.theta_0
    theta_1 = model.theta_1
    
    dtheta_0 = []
    for i in range(len(x)):
        # 𝜃_0+𝜃_1∗𝑥𝑖−𝑦𝑖
        d = theta_0 + theta_1 * x[i] - y[i]
        dtheta_0.append(d)
    return np.mean(dtheta_0)
def cal_dtheta1(model, x, y):
    theta_0 = model.theta_0
    theta_1 = model.theta_1
    
    dtheta_1_ = []
    for i in range(len(x)):
        # 𝜃_0+𝜃_1∗𝑥𝑖−𝑦𝑖
        d = x[i] * (theta_0 + theta_1 * x[i] - y[i])
        dtheta_1_.append(d)
    return np.mean(dtheta_1_)
# 训练步数
tain_step = 50
# 学习率
lr = 0.00001
history_theta_0 = []
history_theta_1 = []
losses = []
linear_regression_model = LinearRegression()
for i in range(tain_step):
    # 计算loss
    y_pred = [linear_regression_model(i) for i in x]
    loss = loss_func(y, y_pred)
    losses.append(loss)
    
    # 计算梯度
    dtheta_0 = cal_dtheta0(linear_regression_model, x, y)
    dtheta_1 = cal_dtheta1(linear_regression_model, x, y)
    theta_0 = linear_regression_model.theta_0
    theta_1 = linear_regression_model.theta_1
    history_theta_0.append(theta_0)
    history_theta_1.append(theta_1)
    
    # 更新梯度
    theta_0 = theta_0 - lr*dtheta_0
    theta_1 = theta_1 - lr*dtheta_1
    linear_regression_model.update(theta_0, theta_1)
plt.plot(losses)
plt.show()
show_grade(dots=(history_theta_0, history_theta_1))
plt.scatter(x, y)
plt.plot([80, 140], [linear_regression_model(i) for i in [80, 140]])
plt.show()
print(linear_regression_model.theta_1)