numpy学习线性回归, 并用matplotlib画动态图

1 篇文章 0 订阅
1 篇文章 0 订阅

线性回归

准备

假设函数为一元一次函数
h = Θ 0 + Θ 1 x h = \Theta _{0} + \Theta _{1}x h=Θ0+Θ1x

代价函数
J ( Θ 0 , Θ 1 ) = 1 2 m ∑ i = 1 m ( h ( x i ) ) − y i ) 2 J(\Theta _{0}, \Theta _{1}) = \frac{1}{2m}\sum_{i=1}^{m}(h(x_{i})) - y_i)^2 J(Θ0,Θ1)=2m1i=1m(h(xi))yi)2
我们的目的就是找到参数 Θ 0 \Theta_0 Θ0 Θ 1 \Theta_1 Θ1使得代价函数值最小

梯度下降方式求

梯度下降算法, 参数 = 参数 - 学习率 * 代价函数对参数求偏导
Θ j = Θ j − α ∂ ∂ Θ j J ( Θ 0 , Θ 1 ) \Theta_j = \Theta_j - \alpha \frac{\partial }{\partial \Theta_j }J(\Theta_0, \Theta_1) Θj=ΘjαΘjJ(Θ0,Θ1)

import numpy as np  # 引入numpy

# 生成数据
x = np.arange(100).reshape(100, 1)
# 按照y = 10x + 100 生成数据, 并且数据会上下100随机误差
y = 10 * x + 100  + np.random.randint(-100, 100, size=(100, 1))

# 假设函数 h = ax + b
# 初始化参数, 这里都设置为0, 也能设置两个随机数
a = 0
b = 0
learning_rate = 0.0001  # 学习率

# 死循环梯度下降
while True:
	# 这里不要把求出的偏导值直接修改参数, 避免影响其他参数的计算, 所以先保留原参数值
    a_spread = np.mean((a*x+b-y)*x)  # 记录a参数求偏导值
    b_spread = np.mean(a*x+b-y)  # 记录b参数求偏导值
    
    a = a - a_spread * learning_rate  # 修改参数
    b = b - b_spread * learning_rate
	
	if abs(a_spread) <= 0.1 and abs(b_spread) <= 0.1:
		# 这里设置一个阈值, 本身最好观察梯度下降函数图像, 发现基本不下降了才停止
		break
print(a, b)  # 打印梯度下降求出的两个参数值

在matplotlib画出图像

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import clear_output, display

# 生成数据
x = np.arange(100).reshape(100, 1)
# 按照y = 10x + 100 生成数据, 并且数据会上下100随机误差
y = 10 * x + 100  + np.random.randint(-100, 100, size=(100, 1))
# 初始化 h = ax + b, a=0, b=0
# 假设函数 h = ax + b
# 初始化参数, 这里都设置为0, 也能设置两个随机数
a = 0
b = 0
learning_rate = 0.0001  # 学习率
while True:
    a_spread = np.mean((a*x+b-y)*x)
    b_spread = np.mean(a*x+b-y)
    a = a - a_spread * learning_rate
    b = b - b_spread * learning_rate
    # 画出函数图像
    _x = np.linspace(x[0], x[-1], 2*len(x))
    _y = _x * a + b
    # 这里可以每隔一定次数在画出图像, 因为b参数会变化很慢
    clear_output(wait=True)  # 清除打印信息
    plt.ylim(0, 1300)  # 控制y轴显示范围
    plt.xlim(0, 200)  # 控制x轴显示范围
    plt.scatter(x, y, s=5)  # 画出散点图
    plt.plot(_x, _y, color='red', linewidth=1.0, linestyle='--')  # 画出假设函数h图像
    plt.annotate(  # 显示一个文本框指向最后一个数据
        s=f"{a=:.2f} {b=:.2f}",  # 文本内容
        xy=(_x[-1], _y[-1]),  # 箭头点所在坐标
        xytext=(_x[-1]+10, _y[-1]-100),  # 文本内容所在坐标
        weight='bold',  # 字体线型
        color='aqua',  # 字体颜色
        arrowprops=dict(arrowstyle='-|>', connectionstyle='arc3', color='red'),
        bbox=dict(boxstyle='round,pad=0.5', fc='yellow', ec='k',lw=1 ,alpha=0.4)
    )
    plt.pause(0.1)
    if abs(a_spread) <= 0.1 and abs(b_spread) <= 0.1:
        plt.savefig('result.png', bbox_inches='tight', pad_inches=0)  # 保存结果
        plt.close()
        break

线性回归拟合过程视频

正规矩阵方式求

公式: Θ = ( X T X ) − 1 X T y \Theta = (X^TX)^-1X^Ty Θ=(XTX)1XTy

import numpy as np
# 生成数据
x = np.arange(100).reshape(100, 1)
# 按照y = 10x + 100 生成数据, 并且数据会上下100随机误差
y = 10 * x + 100 + np.random.randint(-100, 100, size=(100, 1))

# 构建X矩阵
X = np.matrix(np.c_[np.ones((100, 1)), x])  # 添加一列全为1的一列, 作为x0
Theta = (X.T * X).I * X.T * y  # .T是转置, .I是逆矩阵, 逆矩阵也可以用np.linalg.pinv求解伪逆, 避免不存在逆矩阵情况
print(Theta)  # 打印求解后的参数
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我们可以使用最小二乘法对身高和体重之间的关系进行拟合。以下是代码实现: ```python import numpy as np import matplotlib.pyplot as plt # 体重数据 x = np.array([48, 64, 53, 66, 52, 68, 50, 52, 64, 49]) # 身高数据 y = np.array([162, 165, 159, 173, 157, 175, 161, 164, 172, 158]) # 求均值 x_mean = np.mean(x) y_mean = np.mean(y) # 求解回归系数 numerator = 0 # 分子 denominator = 0 # 分母 for i in range(len(x)): numerator += (x[i] - x_mean) * (y[i] - y_mean) denominator += (x[i] - x_mean) ** 2 beta = numerator / denominator # 回归系数 alpha = y_mean - beta * x_mean # 截距 # 出拟合曲线 x_fit = np.linspace(np.min(x), np.max(x), 100) # 用于绘制拟合曲线的x坐标 y_fit = alpha + beta * x_fit # 对应的y坐标 # 出散点图和拟合曲线 plt.scatter(x, y) plt.plot(x_fit, y_fit, 'r') plt.xlabel('Weight (kg)') plt.ylabel('Height (cm)') plt.title('Weight and Height Regression') plt.show() ``` 首先,我们将体重和身高数据分别存储在numpy数组x和y中。然后,我们求出体重和身高的均值x_mean和y_mean。接下来,我们使用最小二乘法求解回归系数。 回归系数beta表示体重对身高的影响程度,回归系数越大,体重和身高之间的关系越密切。截距alpha表示当体重为0时,身高的值。在这里,我们使用最小二乘法求解回归系数的公式为: $$\beta = \frac{\sum_{i=1}^n(x_i - \bar{x})(y_i - \bar{y})}{\sum_{i=1}^n(x_i - \bar{x})^2}$$ $$\alpha = \bar{y} - \beta \bar{x}$$ 最后,我们使用matplotlib库中的scatter和plot函数分别出散点图和拟合曲线,并设置横纵坐标的标签和标题。运行上述代码,即可得到拟合曲线。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值