首页 > 其他分享 >08_线性回归详解

08_线性回归详解

时间:2024-06-16 19:33:28浏览次数:14  
标签:plot plt 08 np 详解 path 线性 theta dot

线性回归详解

1、包导入与数据创建

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
# 绘图全局参数设置
config = {
    "font.family": 'Times New Roman',
    "font.size": 14,
    "font.serif": 'Simsun',
}
matplotlib.rcParams.update(config)

导入需要的数据处理包numpy和绘图包matplotlib

# 随机生成100个样本

X = 2 * np.random.rand(100, 1)
# 使用一次线性公式4+3*x并增加随机数来模拟噪音影响
y = 4 + 3 * X + np.random.randn(100, 1)
# 显示生成的数据
plt.plot(X, y, 'b.')
plt.xlabel('X')
plt.ylabel('y')
plt.axis([0, 2, 0, 15])
plt.show()

image-20240128110214394

2、直接求解法

损失函数:

\(\displaystyle J(\theta) = \frac12\sum^m_{i=1}(y^i - \theta^Tx^i)^2=\frac12\sum^m_{i=1}(h_\theta(x^i)-y^i)^2 = \frac12(X\theta - y)^T(X\theta-y)\)

损失函数求导:

\(\displaystyle \nabla_\theta J(\theta)=\nabla_\theta [\frac12(X\theta - y)^T(X\theta-y)]=\nabla_\theta[\frac12(\theta^TX^T-y^T)(X\theta-y)]\)

\(\displaystyle =\nabla_\theta[\frac12(\theta^TX^TX\theta-\theta^TX^Ty-y^TX\theta+y^Ty)]\)

\(\displaystyle =\frac12(2X^TX\theta-X^Ty-(y^TX)^T)=X^TX\theta-X^Ty\)

让损失函数求导后等于0建立方程求得:

\(\displaystyle \theta = (X^TX)^{-1}X^Ty\)

直接求解

# 增加一列 1, 作为偏置项参数
X_b = np.c_[np.ones((100, 1)), X]
theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
print(theta_best)

image-20240128110227279

# 预测
X_new = np.array([[0], [2]])
X_new_b = np.c_[np.ones((2, 1)), X_new]
y_predict = X_new_b.dot(theta_best)
print(y_predict)

image-20240128110238222

# 绘制回归线
plt.plot(X_new, y_predict, 'r--')
plt.plot(X, y, 'b.')
plt.xlabel('X')
plt.ylabel('y')
plt.axis([0, 2, 0, 15])
plt.show()

image-20240128110250747

from sklearn.linear_model import LinearRegression

# 这里使用的是直接求导的方程方法
lin_reg = LinearRegression()
lin_reg.fit(X, y)
print(lin_reg.coef_)
print(lin_reg.intercept_)

image-20240128110313105

  • 优点:得到的结果是最优解
  • 缺点:由于求解公式中有求逆的存在,而并不是所有的矩阵都能求逆,并且在数据量比较大时,计算速度比较慢,所以有了梯度下降的方法

3、梯度下降准备

  • 正常梯度下降:先随机选取一个初始点,然后一步步逼近最优解

    2

  • 步长太小:会导致求解时间长

    3

  • 步长太大:求解过程跌宕起伏,得到的解不好,所以一般步长宁可小也不能大

    4

  • 局部最优解:在线性回归中一般都不会有局部最优解,因为线性回归是凸函数,但是在有些问题中会存在这样的问题

    5

    对于这种问题需要多做几组实验,在不同的位置选取初始点,在绝大部分机器学习问题中都不存在局部最优解

  • 数据处理标准化:让所有特征数据的取值范围一致,从而方便求解,拿到数据之后基本上都需要进行标准化操作

    6

    标准化只是数据预处理中的一种,在sklearn中有一个专门的预处理模块 sklearn.preprocessing,里面有很多预处理的函数

4、批量梯度下降

公式:

\(\displaystyle J(\theta) = \frac1{2m}\sum^m_{i=1}(h_\theta(x^i)-y^i)^2\)

\(\displaystyle \frac{\partial J(\theta)}{\partial \theta_j} = \frac1m \sum^m_{i=1}(h_\theta(x^i)-y^i)x^i_j\)

\(\displaystyle \theta_j' = \theta_j - \alpha\frac1m \sum^m_{i=1}(h_\theta(x^i)-y^i)x^i_j\)

\(\displaystyle \theta' = \theta - \alpha \frac1m X^T(X\theta - y)\)

# 批量梯度下降
eta = 0.2
n_iterations = 1000
m = len(X_b)
theta = np.random.randn(2, 1)
for iteration in range(n_iterations):
    gradients = 1/m*X_b.T.dot(X_b.dot(theta) - y)
    theta = theta - eta * gradients
print(theta)

image-20240128110407024

我们来尝试不同学习率对模型的影响

# 绘图
theta_path_bgd = []
def plot_gradient_descent(theta, eta, theta_path = None):
    m = len(X_b)
    plt.plot(X, y, 'b.')
    n_iterations = 1000
    for iteration in range(n_iterations):
        y_predict = X_new_b.dot(theta)
        gradients = 1/m*X_b.T.dot(X_b.dot(theta) - y)
        theta = theta - eta * gradients
        if theta_path:
            theta_path.append(theta)
        
        plt.plot(X_new, y_predict, 'r-')
        plt.xlabel('X_1')
        plt.axis([0, 2, 0, 15])
        plt.title(f'eta = {eta}')
theta = np.random.randn(2, 1)

plt.figure(figsize=(10, 4))
plt.subplot(131)
plot_gradient_descent(theta, eta = 0.02)
plt.subplot(132)
plot_gradient_descent(theta, eta = 0.2)
plt.subplot(133)
plot_gradient_descent(theta, eta = 1)

image-20240128110655543

可以直观的看到,当学习率太小时,模型需要很多步才能达到最优解;而学习率太大时,模型确不能达到最优解。所以在实际运用中,学习率宁可小也不能大

5、随机梯度下降

公式:

\(\displaystyle \theta' = \theta - \alpha(h_\theta(x^i)-y^i)x^i_j = \theta - \alpha(x_j^i\theta-y^i)x^i_j\)

theta_path_sgd = []
m = len(X_b)
n_epochs = 10

t0 = 5
t1 = 50
theta = np.random.randn(2, 1)

def learning_schedule(t):
    return t0 / (t1 + t)

for epoch in range(n_epochs):
    for i in range(m):
        if epoch < 4 and i % 2 == 0:
            y_predict = X_new_b.dot(theta)
            plt.plot(X_new, y_predict, 'r-')
        random_index = np.random.randint(m)
        xi = X_b[random_index:random_index+1]
        yi = y[random_index:random_index+1]
        gradients = xi.T.dot(xi.dot(theta) - yi)
        eta = learning_schedule(epoch * m + 1)
        theta = theta - eta*gradients
        theta_path_sgd.append(theta)
        
plt.plot(X, y, 'b.')
plt.axis([0, 2, 0, 15])
plt.show()

image-20240201103421954

6、小批量随机梯度下降

公式:

\(\displaystyle \theta_j' = \theta_j - \alpha\frac1{batch} \sum^{i+batch-1}_{k=1}(h_\theta(x^k)-y^k)x^k_j\)

\(\displaystyle = \theta_j - \alpha \frac1{batch} X_j^T(X_j\theta - y_j)\)

theta_path_mgd = []
n_epochs = 10
minibatch = 16
theta = np.random.randn(2, 1)

for t, epoch in enumerate(range(n_epochs)):
    shuffled_indices = np.random.permutation(m)
    X_b_shuffled = X_b[shuffled_indices]
    y_shuffled = y[shuffled_indices]
    for i in range(0, m, minibatch):
        xi = X_b_shuffled[i:i+minibatch]
        yi = y_shuffled[i:i+minibatch]
        gradients = 1 / minibatch * xi.T.dot(xi.dot(theta) - yi)
        eta = learning_schedule(t)
        theta = theta - eta * gradients
        theta_path_mgd.append(theta)
print(theta)

image-20240201104748270

7、三种梯度下降对比

theta_path_bgd = np.array(theta_path_bgd)
theta_path_sgd = np.array(theta_path_sgd)
theta_path_mgd = np.array(theta_path_mgd)
plt.figure(figsize=(8, 4))
plt.plot(theta_path_sgd[:, 0], theta_path_sgd[:, 1], 'g-+', markersize=3, linewidth=1, label='SGD')
plt.plot(theta_path_mgd[:, 0], theta_path_mgd[:, 1], 'b-o', markersize=3, linewidth=1, label='MGD')
plt.plot(theta_path_bgd[:, 0], theta_path_bgd[:, 1], 'r-s', markersize=3, linewidth=1, label='BGD')
plt.legend(loc='upper right')
plt.axis([3, 4.2, 2.5, 4.5])
plt.show()

image-20240201111126556

看红色的线,可以看到批量梯度下降像是直接往最终结果的方向走;再看蓝色的线,小批量随机梯度下降也是往最终结果方向前进,但是过程有一些波动;最后看绿色的线,随机梯度下降的前进方向波动更大。

标签:plot,plt,08,np,详解,path,线性,theta,dot
From: https://www.cnblogs.com/monarch-yan/p/18251132

相关文章

  • 冲刺08
    fragment_register_select_role.xml<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_......
  • 08梦断代码阅读笔记之三
     自身对于何为软件,何为代码仅有一些肤浅的认识,半学期下来,编程能力也有了较大的提高。但是其中的痛苦和艰辛,也很值得自己去慢慢的回味。书中描述一群人们怀抱着改变世界的理想上路了,却在追寻时发现,那些近在眼前的理想之峰,变得那么的遥不可及;每当翻过一座横亘在面前的山峰时,总以为......
  • 【代码+详解】算法题 : 骨头收集者
    ❗❗❗必看:下列题我全部都使用Java语言写的,并且均可以提交成功,获得Accepted结果的.如果代码和详解看了之后,对答案有任何疑问,都可以在评论区提出来,我都会一个一个回答.❗❗❗感谢大家的支持,如果喜欢我的博客,关注点赞收藏评论一波,非常感谢!!!文章目录......
  • Pytest框架中fixture功能详解
    文章目录1定义Fixture函数2Fixture的函数参数2.1传入其他fixture函数作为参数2.2传入request对象参数示例1:访问fixture的调用者示例2:使用fixture的参数3Fixture的作用域参数scope3.1scope=class场景3.2scope=session场景4Fixture的自动使用参数autouse=......
  • Redis分布式锁详解及电商秒杀功能示例
    Redis分布式锁是一种在分布式系统中,利用Redis的原子操作特性实现的锁机制,用于保护共享资源的并发访问。原理原子性与互斥性Redis分布式锁的核心原理在于利用Redis的某些原子操作(如`SETNX`、`GETSET`、`SET`带特定选项等)来确保锁的获取与释放操作是原子性的,从而保证了锁的......
  • Unreal RecastNavigation 开源项目详解
    0前言Recastnavigation是一个游戏AI导航库,像Unity,UE引擎中都集成了这个开源项目,HALO中使用的也是这个开源库。导航最重要的就是为NPC寻路,以及其他的寻路需求。需要注明的是,这个寻路库虽然厉害。但是他的核心是平面寻路。也就是重力方向一直朝着-Y方向。如果是星球地形,既重......
  • PHP框架详解 - Symfony框架
    PHP框架详解-Symfony框架引言在当今快速发展的Web开发领域,PHP作为一种流行的服务器端脚本语言,一直以其简洁性和高效性受到开发者的青睐。随着Web应用的复杂性不断增加,PHP框架应运而生,为开发者提供了一套更加结构化和模块化的开发方式。在众多PHP框架中,Symfony以其强大的......
  • 第七章 线性判别分析LDA(7.1)
    一、基本代码:sklearn.discriminant_analysis.LinearDiscriminantAnalysis(solver='svd',shrinkage=None,priors=None,n_components=None,store_covariance=False,tol=0.0001,covariance_estimator=None)[source]参数介绍:参数:priors:一个数组,数组中的元素依次指定了每个类......
  • 【Linux】fork()函数详解|多进程
    ......
  • Redisson详解
    目录第1章:Redisson简介第2章:Redisson的架构与原理第3章:Redisson的基本使用连接Redis基本操作高级数据结构操作分布式锁的使用第4章:Redisson的高级特性分布式数据结构发布/订阅模型延迟队列与阻塞队列第5章:Redisson的分布式服务分布式锁的实现与应用分布式集合......