【人工智能基础】线性回归实验分析

实验使用到的库:numpy、matplotlib、scikit-learn
实验使用的开发环境:anaconda、jupyter

一、线性回归

线性回归就是使用一个线性函数(多项式回归可以是曲线)去拟合给定的训练集,测试时,对输入的x值,返回这个线性函数的y值。最终目标是找到y=Θ0 + Θ1x1 + Θ2x2 + …… + Θnxn 函数式中的Θ0、Θ1、Θ2、……、Θn

由于上图中我们能看到存在一个Θ0并不是xi的系数,而Θi是从输入的标准化数据中获得的,所以在标准化数据中我们需要单独添加一列常数项1

实验步骤

1.产生数据

# 产生数据
import numpy as np
# 产生[0,2)的随机数据,作为x值
x = 2 * np.random.rand(100,1)
# 给定一个函数获得y值
y = 4 + 3 * x + np.random.randn(100,1)

2.展示产生的数据(这块只是一个数据展示,不影响整体流程)

# 绘制数据散点图图像
import matplotlib.pyplot as plt
plt.plot(x,y,'b.')
plt.xlabel('x1')
plt.ylabel('y')
plt.axis([0,2,0,15])
plt.show()

产生的数据

3.为数据添加常数项1,并求Θ

numpy.c_[矩阵1,矩阵2]可以讲矩阵1和矩阵2拼接成为一个矩阵
numpy.ones((100,1)) 可以生成一个100行1列的纯1矩阵

# 添加偏置项1
x_b= np.c_[np.ones((100,1)),x]
# 使用公式Θ = (xT ⋅ x)-1 ⋅ xT ⋅ y 求Θ 
# xT表示矩阵x的转置
# (xT ⋅ x)-1 表示 xT ⋅ x的逆
theta_best = np.linalg.inv(x_b.T.dot(x_b)).dot(x_b.T).dot(y)

4.绘制函数图像

# 选取两个点(函数的两个端点)
x_new = np.array([[0],[2]])# 拼接偏置项1
x_new_b = np.c_[np.ones((2,1)),x_new]# 获得预测值
y_predict = x_new_b.dot(theta_best)# 数据绘制
plt.plot(x_new,y_predict,'r--')
plt.plot(x,y,'b.')
plt.xlabel('x1')
plt.ylabel('y')
plt.axis([0,2,0,15])
plt.show()

线性回归函数图像

二、机器学习下的线性回归

在上面的实验中,我们直接使用公式Θ = (xT ⋅ x)-1 ⋅ xT ⋅ y得到了Θ值,但是在实际中我们的机器需要通过如梯度下降之类的算法,逐步减少误差,获取到Θ的值,这个获得Θ的过程就是学习。

scikit-learn给我们提供了线性回归的工具

from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(x,y)
print(lin_reg.coef_)
print(lin_reg.intercept_)

通过这段代码我们最终能得到:

  • lin_reg.coef_,学习结束后得到的Θ值,即每个特征值
  • lin_reg.intercept_,函数的截距值,即Θ0

三、学习率的影响

我们知道。梯度下降就是沿着误差函数对Θ的偏导的负方向找到最小值Θimin

求导公式为 2/m * (ΘT ⋅ x - y) ⋅ xi
其中:ΘT 表示Θ的转置
注:Θ 和 x 在代码中都是矩阵形式,使用ΘT ⋅ x 就相当于对Θixi求和。

梯度下降实现

# 学习率
alpha = 0.1
# 迭代次数
n_iter = 1000
# 样本个数
count = 100
# 初始化theta位置
theta = np.random.randn(2,1)
for iter in range(n_iter):# 对thetaJ求导 = 2/m * 求和(thetaT * x - y) * xJgradients = 2 / count * x_b.T.dot(x_b.dot(theta) - y)# 更新thetatheta = theta - alpha * gradients
print(theta)

最后theta是一个2*1的矩阵存储着Θ0和x对应的权重Θ

定义学习率影响因素的函数

# 这个代码也是全量梯度下降的代码(全部的Θ值都参与梯度下降计算)
# theta_path_bgd存储每次梯度下降得到的Θ值
theta_path_bgd = []
def plot_gradigent_descent(theta, alpha, theta_path = None):count = len(x_b)plt.plot(x,y,'b.')n_iter = 1000# 进行1000次迭代计算for iter in range(n_iter):y_predict = x_new_b.dot(theta)plt.plot(x_new,y_predict,'r--')# 计算梯度gradients = 2 / count * x_b.T.dot(x_b.dot(theta) - y)# 新的Θ值为 旧Θ值 - 学习率 * 梯度theta = theta - alpha * gradientsif theta_path is not None:theta_path.append(theta)# 绘制图像plt.xlabel('x_1')plt.axis([0,2,0,15])plt.title('alpha={}'.format(alpha))

调用函数绘制图像

theta = np.random.randn(2,1)
plt.figure(figsize=(10,4))
plt.subplot(131)
plot_gradigent_descent(theta,alpha = 0.02)
plt.subplot(132)
# 存储全量梯度下降的过程
plot_gradigent_descent(theta,0.1,theta_path_bgd)
plt.subplot(133)
plot_gradigent_descent(theta,alpha = 0.5)
plt.show()

从图中可以看出:

  • 学习率过小(0.02)可以获得正确的Θ值,但是每次学习效率极低
  • 学习率过大(0.5)虽然效率高,但是计算结果有误

学习率影响

四、不同梯度下降的对比

全量梯度下降已经在学习率中做过了

随机梯度下降

每次去一个Θ值进行梯度下降

theta_path_sgd = []
count = len(x_b)
# 迭代次数
n_epochs = 50t0 = 5
t1 = 50# 学习率修改
def learning_schedule(t) :return t0 / (t1 + t)theta=np.random.randn(2,1)for epoch in range(n_epochs):# 遍历样本for i in range(count):# 只画第一批前二十个if epoch == 0 and i < 20:y_predict = x_new_b.dot(theta)plt.plot(x_new,y_predict,'r--')random_index = np.random.randint(count)# 选中一个值xi = x_b[random_index:random_index + 1]yi = y[random_index:random_index + 1]# 对选中值进行梯度下降gradients = 2 * xi.T.dot(xi.dot(theta) - yi)alpha = learning_schedule(epoch * count + i)theta = theta - alpha * gradientstheta_path_sgd.append(theta)
plt.plot(x,y,'b.')
plt.axis([0,2,0,15])
plt.show()
print(theta)

随机梯度下降

小批量梯度下降

即选中一批数据进行梯度下降

theta_path_mgd = []
count = len(x_b)
# 迭代次数
n_epochs = 50
# 一批数量
minibatch = 16theta=np.random.randn(2,1)t = 0
for epoch in range(n_epochs):# 洗牌shuffled_indices = np.random.permutation(count)x_b_shuffled = x_b[shuffled_indices]y_shuffled = y[shuffled_indices]for i in range(0,count,minibatch):t += 1# 获取一批数据xi = x_b_shuffled[i:i + minibatch]yi = y_shuffled[i:i + minibatch]# 对获取到的这批数据进行梯度下降gradients = 2 / minibatch * xi.T.dot(xi.dot(theta) - yi)alpha = learning_schedule(t)theta = theta - alpha * gradientstheta_path_mgd.append(theta)print(theta)

三种梯度下降方式的对比

数据处理

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],'r-s',linewidth=1,label='SGD')
plt.plot(theta_path_mgd[:,0],theta_path_mgd[:,1],'b-+',linewidth=2,label='MGD')
plt.plot(theta_path_bgd[:,0],theta_path_bgd[:,1],'g-o',linewidth=3,label='BGD')
plt.legend(loc='upper left')
plt.axis([2,4,1,5.0])
plt.show()

三种梯度下降方式对比

可以看到:

  • 全量梯度下降一直在向目标逼近
  • 小批量梯度下降略有波动
  • 随机梯度下降的波动很剧烈

五、多项式回归(非线性回归)

在实际情况中,我们得到的数据不一定能通过一次函数拟合,需要更高次的函数才能更好的拟合训练数据

创建数据

# 多项式回归
count = 100
# x(-3,+3)
x = 6 * np.random.rand(count,1) - 3
# y = 0.5 * x^2 + x
y = 0.5 * x**2 + x + np.random.randn(count,1)plt.plot(x,y,'r.')
plt.show()

多项式回归数据集

数据处理

PolynomialFeatures可以把我们的输入的数据处理为更高幂次的形式

from sklearn.preprocessing import PolynomialFeatures
poly_features = PolynomialFeatures(degree = 2, include_bias = False)x_poly = poly_features.fit_transform(x)print(x[0])
print(x_poly[0], x[0][0]**2)

这里我们把原本的x处理成x和x^2的形式

PolynomialFeatures处理结果

二次函数图像绘制

numpy.linspace(-3,3,100)生成[-3,3]的100个等距数值数组

from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(x_poly, y)x_new = np.linspace(-3,3,100).reshape(100,1)
# 多项式转换
x_new_poly = poly_features.transform(x_new)
y_new = lin_reg.predict(x_new_poly)plt.plot(x,y,'b.')
plt.plot(x_new,y_new,'r--',label='predcition')
plt.legend()
plt.show()

多项式函数图像

六、模型复杂度的影响

这里的复杂度就是指模型的最高幂次

Pipeline用于将多个数据处理步骤和机器学习模型串联起来,形成一个有序的工作流程,即“机器学习流水线”

StandardScaler用于数据的标准化

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScalerplt.figure(figsize=(12,6))# 分别绘制50次,2次、1次的函数图像拟合训练数据
for style, width, degree in (('g-',1,50),('b--',2,2),('r-+',3,1)):poly_features = PolynomialFeatures(degree = degree, include_bias = False)std = StandardScaler()lin_reg = LinearRegression()pr= Pipeline([('poly_features', poly_features),('StandardScaler', std),('regression', lin_reg)])pr.fit(x,y)y_new_2 = pr.predict(x_new)plt.plot(x_new,y_new_2,style, label = str(degree), linewidth=width)
plt.plot(x,y,'b.')plt.axis([-3,3,-5,10])plt.legend()
plt.show()

从下图中可以看到高复杂度的模型试图拟合更多的数据导致波动极大,在测试集中的表现可能还不如低复杂度的模型,这种情况称为过拟合

模型复杂度的影响

七、样本数量的影响(过拟合的避免)

样本量影响实验

def plot_learning_curves(model,x,y):x_train,x_val,y_train,y_val = train_test_split(x,y,test_size=20,random_state=0)# 存储训练方差和实际方差train_errors,val_errors = [],[]# 取1个 到 count个 样本量for m in range(1, len(x_train)):model.fit(x_train[:m],y_train[:m])# 截取样本y_train_predict = model.predict(x_train[:m])y_val_predict = model.predict(x_val)# 存储结果train_errors.append(mean_squared_error(y_train[:m],y_train_predict[:m]))val_errors.append(mean_squared_error(y_val,y_val_predict))plt.plot(np.sqrt(train_errors),'r-+',linewidth=2,label='train_error')plt.plot(np.sqrt(val_errors),'b-',linewidth=3,label='val_error')plt.legend()lin_reg = LinearRegression()
plot_learning_curves(lin_reg,x,y)

在低样本数据量的时候两者的差距很大

而大样本量的时候两个差距会缩小

样本数据量的影响

多项式的过拟合风险

# 多项式回归的拟合风险
# 使用10次函数尝试拟合
pr= Pipeline([('poly_features', PolynomialFeatures(degree = 10, include_bias = False)),('regression', LinearRegression())])
plot_learning_curves(pr,x,y)
plt.axis([0,80,0,45])
plt.show()

多项式的过拟合风险

八、正则化

正则化的目的就是当两个模型对训练集给出的结果基本相同时,选取更稳定的模型
正则化通过对误差函数增加一个带权重的额外的值(岭回归中使用Θ^2求和,Lasso使用Θ的绝对值)

岭回归

from sklearn.linear_model import Ridge
np.random.seed(42)
count = 20
x = 3 * np.random.rand(count,1)
y = 0.5 * x + np.random.randn(count,1) / 1.5 + 1
x_new = np.linspace(0,3,100).reshape(100,1)# alpha在这里表示正则的权重,越大则倾向于越稳定的模型
def plot_model(model_class, polynomial, alphas, ** model_kargs):# alphas[0]-’b-‘:alphas[0]-'g--':alphas[2]-’r.‘for alpha,style in zip(alphas,('b-','g--','r.')):model = model_class(alpha,**model_kargs)if polynomial:model = Pipeline([('poly_features', PolynomialFeatures(degree = 10, include_bias = False)),('StandardScaler', StandardScaler()),('regression', model)])model.fit(x,y)y_new_regul = model.predict(x_new)width = 2 if alpha > 0 else 1plt.plot(x_new,y_new_regul,style,linewidth = width, label='alpha={}'.format(alpha))plt.plot(x,y,'b.',linewidth=3)plt.legend()
plt.figure(figsize=(10,5))
plt.subplot(121)
plot_model(Ridge,polynomial=False,alphas = (0,10,100))
plt.subplot(122)
plot_model(Ridge,polynomial=True,alphas = (0,10**-5,1))

岭回归

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/4047.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Selenium一本通

Selenium中文官方文档 从一个测试脚本说起 from selenium import webdriver #引入selenium webdriver模块 driver webdriver.Firefox() #初始化Firefox浏览器的webdriver对象&#xff0c;启动浏览器 driver.get("http://cn.bing.com/") #跳转到对应页面 assert Bi…

Jammy@Jetson Orin - Tensorflow Keras Get Started: Concept

JammyJetson Orin - Tensorflow & Keras Get Started: Concept 1. 源由2. 模型2.1 推理流程2.1.1 获取图像2.1.2 算法识别2.1.3 判断决策 2.2 理想情况2.2.1 多因素输入2.2.2 理想识别概率 2.3 学习过程2.3.1 标记训练集2.3.2 损失函数2.3.3 训练网络2.3.4 渐进方法 3. 总…

jvm(JVM快速入门、stack栈、堆、GC垃圾回收、Arthas)

文章目录 1. JVM快速入门1.1. 结构图1.2. 类加载器ClassLoader1.3. 执行引擎Execution Engine1.4. 本地接口Native Interface1.5. Native Method Stack1.6. PC寄存器(程序计数器)1.7. Method Area方法区 2. stack栈3. 堆3.1. 堆体系概述3.1.1. 新生区3.1.2. 老年代3.1.3. 永久代…

Python 打包:pyinstaller

目录 为什么选择它用法详解所有命令常规-h-v、 --version--distpath DIR--workpath Workpath-y、 --noconfirm--upx dir upx_dir Upx-a、 --ascii--clean--log-level LEVEL 生成内容-D、 --onedir-F、 --onefile--specpath DIR-n NAME&#xff0c;--NAME NAME-w 执行程序 为什么…

python基础知识点(蓝桥杯python科目个人复习计划66)

今日复习内容&#xff1a;算法双周赛 第一题&#xff1a;疯狂星期六 题目描述&#xff1a; 麦肯鸡是一家名声在外的汉堡店&#xff0c;他们最近推出了一份名为vivo50的套餐&#xff0c;只需要在门口大声喊出vivo50&#xff0c;就可以获得这个套餐。 现在&#xff0c;请你打…

【VUE】解决 Element UI 中 el-tab 切换时 ECharts 渲染宽度问题

解决 Element UI 中 el-tab 切换时 ECharts 渲染宽度问题 在使用 Element UI 的 el-tabs 组件时&#xff0c;我们常常会遇到一个问题&#xff1a;当 ECharts 图表被放在非当前激活的 Tab 内时&#xff0c;图表无法正确渲染其宽度和高度。由于在 Tab 未激活状态下&#xff0c;图…

[Java、Android面试]_21_Dalvik VM与JVM的区别

欢迎查看合集&#xff1a; Java、Android面试高频系列文章合集 文章目录 1. 结构2. 编译3. 运行环境4. Dalvik进程管理 Dalvik是android系统中的虚拟机&#xff0c;JVM是java虚拟机。 Dalvik VM可以支持将已转化为.dex文件格式的java应用程序的运行&#xff0c;.dex是专为Dalvi…

Windows程序设计 - 字符与字符串处理

目录 字符编码的问题 ANSI Vs Unicode 函数版本区分 C RunTime库 老生常谈的ASCII和UNICODE支持性 安全字符串函数 推介的字符和字符串处理的方式 ASCII与UNICODE互转 Reference 字符编码的问题 对于一些像我这样的初学者&#xff1a;很喜欢认为字符串的处理就是将字…

了解ASK模块STX883Pro和超外接收模块SRX883Pro的独特之处 STX883Pro模块具有以下特点:

高发射功率&#xff1a;STX883Pro具有较高的发射功率&#xff0c;可实现长距离的信号传输&#xff0c;适用于需要覆盖广泛区域的应用场景。 高频率稳定性&#xff1a;具备稳定的频率输出&#xff0c;确保信号传输的可靠性和一致性&#xff0c;避免频率漂移导致的通信故障。 大…

Ubuntu 18.04 安装 CMake Ceres-Solver 记录

1. 安装 CMake-3.22.1 不可卸载原有版本 CMake&#xff08;防止 ROS 出现问题&#xff09;&#xff0c;只需建立软链接即可 1. 源码下载并解压wget https://cmake.org/files/v3.22/cmake-3.22.1.tar.gz tar -xvzf cmake-3.22.1.tar.gz2. 移动到合适目录sudo mv cmake-3.22.1 /u…

C++ | Leetcode C++题解之第48题旋转图像

题目&#xff1a; 题解&#xff1a; class Solution { public:void rotate(vector<vector<int>>& matrix) {int n matrix.size();// 水平翻转for (int i 0; i < n / 2; i) {for (int j 0; j < n; j) {swap(matrix[i][j], matrix[n - i - 1][j]);}}//…

Thread方法具体解析

对于run方法 如果该线程是使用单独的 Runnable run 对象构造的&#xff0c;则调用该 Runnable 对象的 run 方法&#xff1b;否则&#xff0c;此方法不执行任何操作并返回。 对于start方法 导致该线程开始执行&#xff1b; Java虚拟机调用该线程的run方法。 这里介绍一个快捷键…

Java Spring 中构造函数注入和Setter注入的优缺点

在使用Java Spring框架进行依赖注入时&#xff0c;我们常常会遇到构造函数注入和Setter注入两种方式。这两种方式各有优缺点&#xff0c;本文将对它们进行比较和分析&#xff0c;帮助开发者在实际项目中做出合适的选择。 构造函数注入 构造函数注入是通过在类的构造函数中传入…

Windows Vscode ModuleNotFoundError: No module named

故障现象&#xff1a; Windows Vscode 经常会遇到模块路径查找失败的异常。 如运行2_from_import_test.py后&#xff0c;报错&#xff1a; 发生异常: ModuleNotFoundError No module named programmer File "D:\leolab\programmer\2_from_import_test.py", line 8…

什么是数字化运营?

目录 一、什么是数字化运营&#xff1f; 二、数字化运营的重要性是什么&#xff1f; 三、数字化运营的具体步骤和措施是什么&#xff1f; 四、数据化决策是什么&#xff1f; 一、什么是数字化运营&#xff1f; 数字化运营是利用数字技术和数据分析来优化企业的业务流程和运…

C语言 | Leetcode C语言题解之第51题N皇后

题目&#xff1a; 题解&#xff1a; int solutionsSize;char** generateBoard(int* queens, int n) {char** board (char**)malloc(sizeof(char*) * n);for (int i 0; i < n; i) {board[i] (char*)malloc(sizeof(char) * (n 1));for (int j 0; j < n; j) board[i][…

LeetCode-104-二叉树最大深度

题目&#xff1a; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 思路&#xff1a;不断往下遍历&#xff0c;每往深层遍历一层&#xff0c;深度加一&#xff0c;当遍历到null&#xff0c;与当前最大…

Linux内核驱动开发-006内核定时器

1驱动程序 /*************************************************************************> File Name: timer.c> Author: yas> Mail: rage_yashotmail.com> Created Time: 2024年04月23日 星期二 19时20分42秒*************************************************…

每日JAVA高级面试题

Java 高级面试问题及答案 以下是一些在Java高级面试中可能会遇到的问题&#xff0c;以及对这些问题的探讨和回答。 问题 1: Java内存模型是什么&#xff1f;请解释其重要性。 探讨&#xff1a; Java内存模型&#xff08;Java Memory Model, JMM&#xff09;是Java虚拟机&…

【unity】三维数学应用(计算线和面的交点)

【unity】三维数学应用&#xff08;计算线和面的交点&#xff09; 实现方法有多种&#xff0c;下面介绍一种简单的方法。利用一个点指向面上任意点的向量&#xff0c;到该面法线的投影长度相同的基本原理&#xff0c;结合相似三角形既可以求出交点。 原理 如下图 GD组成的线段…