机器学习初识-第二章(数据集,基本术语:样本,特征,特征向量,标签,模型 。机器学习三要素,监督学习,特征工程,欠拟合,过拟合,线性回归,损失函数,正则化,梯度下降法,模型评价指标 )
在此致谢尚硅谷,黑马免费课程,以及豆包大模型帮我解答疑惑
以下图片内容,大多出于这两个课程
目录
验证集:调节超参数的数据 -(超参数,假如y=f(x) =2x^2+3 我们需要把这些参数,找到一个最优秀的出来)
样本:数据集中一条数据是关于一个事件或对象的描述,称为一个样本
特征:数据集中一列反映事件或对象在某方面的表现或性质的事项,称为特征
超参数:由用户设置的参数,不能通过训练自动学习,如学习率,正则化系数等
斯皮尔曼相关系数-(等级变量之间的皮尔逊,不要求是线性关系,适用于非线形关系或者数据不符合正态分布的情况)
一、先明确:5 阶的本质是 “多项式特征”,和 sinx 展开无关
机器处理某个特定任务,以大量的经验为基础,对任务完成的好坏,给予一定的评判标准,通过分析经验数据,任务完成的更好了。
研究计算机对于特定任务的性能,逐步进行改善的算法和统计模型
通过输入海量训练数据对模型进行训练,使模型掌握数据所蕴含的潜在规律,进而对新输入的数据进行准确的分类或者预测

常用术语
数据集
训练集:用于训练模型的数据
验证集:调节超参数的数据 -(超参数,假如y=f(x) =2x^2+3 我们需要把这些参数,找到一个最优秀的出来)
测试集:用于评估模型性能的数据
样本:数据集中一条数据是关于一个事件或对象的描述,称为一个样本
特征:数据集中一列反映事件或对象在某方面的表现或性质的事项,称为特征
特征向量:将样本的所有特征表示为向量的形式,输入到模型中
标签:监督学习中每个样本的结果信息,也称作目标值
模型:一个机器学习算法与训练后的参数集合,用于预测或分类
参数:模型通过训练学习到的值,如线性回归中的权重和偏置
超参数:由用户设置的参数,不能通过训练自动学习,如学习率,正则化系数等

机器学习三要素
模型+策略+算法
策略:选取最优模型的评价准则
算法:选取最优模型的具体方法
通常分类:
有监督学习,无监督学习,半监督学习,强化学习
模型分类:概率模型/非概率模型,线性模型/非线性模型
学习技巧:贝叶斯学习,核方法等
有监督学习:提供数据,并提供数据,对应结果的机器学习过程 -效果更加准确,但是不一定有条件
无监督学习:提供数据,并且不提供数据对应结果的机器学习过程
算法从没有被标记或分类的侧额是数据中学习
无监督学习算法不是响应反馈,而是识别数据中的共性特征,对于一个新数据,可以通过判断其中是否存在这种特征,来做出相应的反馈
无监督学习的核心应用是统计学中的密度估计和聚类分析(比如谷歌新闻,每天对很多新闻进行分组,然后按主题显示给用户,谷歌新闻做打底就是搜索新闻事件)
强化学习:通过与环境交互并获取延迟返回进而改进行为的学习过程
监督学习
监督学习算法构建了包含输入和所需输出的一组数据的数学模型,这些数据称为训练数据,由一组训练样本组成
监督学习主要包括分类和回归
当输出被限制为有限的一组值(离散数值)时使用分类算法,当输出可以具有范围内的任何数值(连续数值)时候使用回归算法-(线性回归)
相似度学习是和回归和分类都密切相关的一类监督机器学习,他的目标是使用相似性函数从样本中学习,这个函数可以度量两个对象之间的相似度或者关联度,他在排名,推荐系统,视觉识别跟踪,人脸识别等方面有很好的应用场景。
- 收集数据(收集用于训练和测试的数据集,确保数据代表了实际问题的不同方面)
- 数据清洗(去除一些脏数据,不可用的数据)
- 特征工程(对数据进行转换和格式化,以确保他适合机器学习模型训练)
- 选择算法(选择适合任务类型,分类,回归,聚类等)和数据特征等机器学习算法
- 模型训练(使用训练数据集来训练模型,让模型从数据中学习规律或模式)
- 模型评估(使用测试数据集评估模型等性能,确定是否达到了预期的目标)
- 模型优化(确保模型具有较好性能的基础上,提高模型的效果)
- 模型部署(训练号的模型部署生产环境)
特征工程(数据的预处理部分)
对原始数据的处理,转换和构造,生成新的特征,选择有效的特征,从而提高模型的性能,
特征工程就是将原始数据转化为更好表示问题的形式,帮助模型更好理解和学习数据中的规律
特征选择
从原始特征中挑选出目标变量关系最密切的特征,提出冗余,无关或噪声特征,这样可以减少模型复杂度,加速训练过程,减少过拟合(后面介绍)的风险
不会创建新特征,也不会改变数据结构
1.过滤法 -给予统计测试(卡方检验,相关系数,信息增益),来评估特征与目标变量之间的关系,选择最相关的特征
(方差越大越好,数据要有偏差,这样才会对我们有贡献)
2.包裹法 -使用模型(递归特征消除RFE)来评估特征的重要性,并根据模型的表现进行特征选择
(使用特征干扰,比如
加入随机噪声,模型的表现应该差一点(模型越差,特征就越重要-本身的添加了相同的噪声
)
3.嵌入法 -使用模型本身的特征(决策树的特征重要性,L1正则化的特征选择)选择机制,来选择最重要的特征
(如,二叉树,选择哪条路,就相当于选特征的意思)
特征转化
- 归一化 - 将特征缩放到特定的范围(0-1之间,对尺度敏感的模型(如KNN,SVM),要知道他的范围,才可以缩放,图像数据很适合这么处理,比如像素点,是rgb(255)这种,假如表示一个像素点 0-255之间的像素点,上下限就确定了
- 标准化 - 通过减去均值,并除以标准差,是特征的分布具有均值0,标准差1 (让他原有的分布,标准分布), (假如有一个类似正态分布,有很少的点,跑路的很远,这就来缩放就不合理)
- 对数变换 - 对于有偏态的分布(如收入,价格等),对数变换可以将其转化为更接近正态分布的形式。 那么你的一万米 和一亿米, 假如觉得这个差别太大,没必要因为这个特殊数据,调整我们的分布情况 ,假如让他缩小一下 比如log 10 就差了4和 8
- 类别变量的编码
- 独热编码 :将类别型变量转化为二进制列,常用语无序类别特征(比如color 红(100)绿(010)蓝(001) 可以理解为数值大小有区别 )
- 标签编码:将类别型变量映射为整数,常用语有序类别特征(0,1,2)
- 目标编码:将类别型变量的每个类别替换为其对应目标变量的平均值
- 频率编码:将类别变量的每个类别替换为该类别在数据集中的出现频率 (R 60次G20次 B30次)
特征构造
基于现有的特征创造出新的,有代表性的特征,通过组合,转换,聚合现有的特征,形成更好反映数据规律的特征
- 交互特征:两个特征组合起来,形成新的特征,如年龄+收入
- 统计特征:从原始特征中提取统计值,比如求某个时间窗口的平均值,最大值,最小值,标准差, 如时间序列中国,从原始数据提取每个小时,每日的平均值
- 日期和时间特征
- 从日期时间数据中提取,星期几,月份,年份,季度等特征-- 如2025-10-24转化为星期几,是否节假日等,月末月初等
特征降维
当数据集的特征数量非常大的时候,特征降维可以帮助减少计算复杂度并避免过拟合,通过降维方法,可以保持数据本质的情况减少特征的数量
- 主成分 分析(PCA):通过线性变换将原始特征,映射到一个新的空间,使新的特征可能保留数据的方差
- 线性判别分析(LDA):一种监督学习的降维方法,通过最大化类间距离与类内距离的比率来降维
- t_SNE(t分布随机近邻嵌入) :一种非线形的降维方法,通过最大类间距离与类内的距离的比率来降维
- 自编码器(Auto Encoder ) --一种神经网络模型,通过压缩编码起来实现数据的降维。
LDA还有一个是(隐狄利克雷分配,要有区分)
机器学习建模流程
数据加载
数据预处理
特征工程
模型训练
模型评估
模型预测
过拟合
让模型在 “未见过的数据” 上表现良好(即泛化能力强),而过拟合恰恰是模型偏离这一目标的典型问题。简单来说,过拟合是模型 “学过头” 了,把训练数据中的噪声、偶然规律甚至错误当成了数据的 “通用规律”,导致它在训练数据上表现极佳,但在新数据(测试 / 实际数据)上表现糟糕。
常用方法
特征有的很关键,有点特征用处不大
特征选择,在特征工程中,最基本,常见的操作
训练模型时候也会遇上维度灾难,即特征数量过多,我们希望在确保不丢失重要特征的前提下,减少维度的数量,来降低训练模型的难度,因此,在特征工程中,也适用特征降维
线性回归引入

y=w转置+b 分为一元/多元
线性回归介绍:用线性公式描述多个自变量(特征),和1个因变量(标签)之间关系的,对其关系进行建模,基于特征预测标签
线性回归:监督学习 . ->. 有特征,有标签,且标签是连续的
一元线性回归: 1个特征列+1个标签列
多元:多个标签列+1个标签列
公式:
一元线性回归
y= kx +b -> wx+b
k:数学叫斜率,机器学习叫weight (权重)- : w
b:数学中叫截距,机器学习中Bias(偏置),简称: b
多元线性回归
y=w1x1+w2x2+w3x3 ..... +wnxn +b
=w的转置*x + b
![]()
低方差过滤法
对于特征的选择,可以基于方差来判断,低方差意味着,特征的样本值几乎相同,对预测影响效果极小,可以将它去掉
#sklearn 著名机器学习的库 from sklearn.feature_selection import VarianceThreshold #低方差过滤:删除方差低于0.01 var_threash=VarianceThreshold(threshold=0.01) X_filtered=var_thresh.fit_transform(X)完整代码:
#构造特征 import numpy as np #生成一个包含 100 个符合标准正态分布(均值为 0,标准差为 1)的随机数数组,并将其打印出来。 a=np.random.randn(100) print(a) #打印方差 print("a的方差",np.var(a)) #生成一个包含 100 个符合标准正态分布(均值为 0,标准差为 0.01)的随机数数组,并将其打印出来。 ->计算方差,每个数据样本,减去均值,平方 b=np.random.randn(100)*0.1 print("b的方差",np.var(b)) #可以直接定义他的均值和方差 c=np.random.normal(5,0.1,size=100) print("c的方差",np.var(c)) #构造特征向量(输入数据X), a和b堆一起 ,数值方向的堆叠.T X =np.vstack((a,b)).T print(X) print(X.shape)我们想要的是100个样本,都有两个特征 (100,2)
多个一维特征组合成符合模型输入要求的 “样本 - 特征” 矩阵
#低方差过滤 from sklearn.feature_selection import VarianceThreshold vt=VarianceThreshold(0.009) X_filterd=vt.fit_transform(X) # print(X_filterd) print("b的实际方差:", np.var(b, ddof=1)) print(X_filterd.shape) 这段代码使用 VarianceThreshold 进行低方差特征过滤,核心逻辑是:剔除方差低于指定阈值(这里是 0.01)的特征,保留方差较高的特征。具体过滤过程如下: 1. 原理:为什么用方差过滤? 特征的 “方差” 反映了其取值的波动程度: 方差高的特征:取值差异大,携带的信息量多(例如 “年龄” 可能有较大波动); 方差低的特征:取值几乎不变(例如 99% 的样本取值都是 “0”),携带的信息量极少,对模型训练帮助很小。 VarianceThreshold 正是通过计算每个特征的方差,过滤掉那些方差低于阈值的 “低信息量特征”,从而实现降维。 2. 具体过滤步骤(以你的代码为例): 假设你的原始特征矩阵 X 是 (100, 2) 形状(100 个样本,2 个特征,即之前的 a 和 b 两个特征): 步骤 1:计算每个特征的方差 vt.fit(X) 会先遍历 X 的每一列(每个特征),计算其方差: 假设特征 1(原 a)的方差为 var1(比如 var1 ≈ 1.0,因为 a 是标准正态分布,方差理论上为 1); 假设特征 2(原 b)的方差为 var2(比如 var2 ≈ 0.01,因为 b 是标准差 0.1 的正态分布,方差理论上为 0.01)。 步骤 2:根据阈值筛选特征 你设置的阈值是 0.01,因此: 方差 ≥ 0.01 的特征会被保留(var1 ≥ 0.01 → 特征 1 保留); 方差 < 0.01 的特征会被剔除(如果 var2 < 0.01 → 特征 2 被剔除,若 var2 = 0.01 则保留,取决于实际计算的方差)。 步骤 3:生成过滤后的特征矩阵 vt.transform(X) 会根据筛选结果,只保留符合条件的特征列,得到 X_filtered: 如果两个特征的方差都 ≥ 0.01 → X_filtered 形状仍为 (100, 2); 如果只有 1 个特征符合条件 → X_filtered 形状变为 (100, 1); 如果都不符合 → 会报错(因为不能保留 0 个特征) 问题二: 那么b是整个样本集 ,他的100个数据,b的方差理论是小于等于0.01,所以要把b这个整体样本集都删除吗? b 不是 “样本集”,而是 “一个特征”(100 个样本在这个特征上的取值)。低方差过滤的对象是 “特征”,而不是 “样本”。 具体解释: b 的本质是 “一个特征”你构造的 X 是 (100, 2) 的特征矩阵: 100 行 → 100 个样本(每个样本是一个观测对象); 2 列 → 2 个特征(a 和 b 分别是两个特征,每列是该特征在 100 个样本上的取值)。 因此,b 是 “第二个特征”,它的 100 个数据是 “这个特征在所有样本上的取值”,而非 “样本集”。 过滤逻辑:删除 “低方差的特征”,而非样本VarianceThreshold(0.01) 的作用是: 计算每个特征(a 和 b 这两列)的方差; 如果某个特征的方差 小于阈值(0.01),则删除整个特征列(即该特征从所有样本中被移除); 样本本身不会被删除,只是样本的特征数量可能减少。 b 是否会被删除? b 的理论方差是 0.01(因为 b = np.random.randn(100)*0.1,标准差 0.1,方差 = 0.1²=0.01); 由于 VarianceThreshold 保留方差 ≥ 阈值的特征,因此 b 的方差等于 0.01 时,会被保留; 如果实际计算的方差因随机波动略小于 0.01(比如 0.0099),则 b 这个特征会被整体删除(即 X_filtered 会变成 (100, 1),只保留 a 特征)。
相关系数法(皮尔逊)
通过计算特征与目标变量或特征之间的相关性,筛选出高相关性特征(与目标相关)或剔除冗余特征(特征间高度相关)
- 皮尔逊相关系数 -高中那个相关系数r - 取值范围[ -1 , 1 ]
正相关:值接近1,说明特征随目标变量增加而增加
负相关:值接近-1,特征随目标变量减少而溅洒红
无关:值接近0,双方无明显关系
import pandas as pd advertising=pd.read_csv('/Users/lcl/PycharmProjects/ml-tutorial/data/advertising.csv') print(advertising.head()) print(advertising.describe()) print(advertising.shape) #数据预处理 #去掉第一列ID,因为只是计数,并没有什么用 advertising.drop(advertising.columns[0],axis=1,inplace=True) #去掉空值,不清楚里面有没有空值,给他去掉 advertising.dropna(inplace=True) #提取特征和标签(目标值) , # 代码 X = advertising.drop("Sales", axis=1) 的作用,就是从原始数据中去掉 “目标列(Sales)”,留下所有 “特征列(TV、Radio、Newspaper)”,形成特征矩阵 X。 X=advertising.drop("Sales",axis=1) Y=advertising["Sales"] print(X.shape) print(Y.shape) #计算皮尔逊相关系数 print(X.corrwith(Y,method="pearson"))
下面的那个,是corr是直接计算相关系数,那么就不加Y,计算的X内部的相关系数,使用包含x也包含y的时候调用(而不是X/Y单独调用),斜对角线全是1
谁对销售额影响最大 并且下面的那个可以放下对角的相关系数是1
再比如热力图,看起来更加直观
print(advertising.corr(method="pearson")) #%% #将相关系数矩阵,转换为热力图 import seaborn as sns import matplotlib.pyplot as plt corr_matrix=advertising.corr(method="pearson") print(corr_matrix) sns.heatmap(corr_matrix,annot=True)
#将相关系数矩阵,转换为热力图 import seaborn as sns import matplotlib.pyplot as plt corr_matrix=advertising.corr(method="pearson") print(corr_matrix) #cmap对应颜色方案 sns.heatmap(corr_matrix,annot=True,cmap="coolwarm",fmt='.2f') plt.title("Feature Correlation Matrix") plt.show()
斯皮尔曼相关系数-(等级变量之间的皮尔逊,不要求是线性关系,适用于非线形关系或者数据不符合正态分布的情况)
dI差别越大,那么1减去之后就会越小,假如差不多,那么就是1-0,因此
这个0是列名,就是没有的话,默认就是0
import pandas as pd #定义数据 # 每周学习时长 X = [[5], [8], [10], [12], [15], [3], [7], [9], [14], [6]] # 数学考试成绩 y = [55, 65, 70, 75, 85, 50, 60, 72, 80, 58] X=pd.DataFrame(X) y=pd.Series(y) #计算斯皮尔曼相关系数 print(X.shape) print(y.shape) print(X.corrwith(y,method='spearman'))计算过程
主成分分析(PCA)
一种常用的降维技术,通过线形变换将高维数据投影到低维空间,同时保留数据的主要变化模式。
import numpy as np import matplotlib.pyplot as plt from sklearn.decomposition import PCA #生成数据 np.random.randn(1000, 3) 生成的是一个 二维数组(矩阵),其中 3 代表数组的 “列数”(对应特征维度),1000 代表 “行数”(对应样本数) #[[x11, x12, x13], # 样本1:3个特征(x11、x12、x13) #[x21, x22, x23], # 样本2:3个特征 #[x1000_1, x1000_2, x1000_3]] # 样本1000:3个特征 X=np.random.randn(1000,3) print(X.shape) #使用PCA进行降维,将3维降为2维 pca=PCA(n_components=2) X_pca=pca.fit_transform(X) print(X_pca.shape) #可视化 #转换3维数据可视化 。画布大小: 第一个参数 12 表示画布的宽度为 12 英寸; 第二个参数 4 表示画布的高度为 4 英寸。 fig=plt.figure(figsize=(12,4)) #三维数据 数 × 列数 × 索引” 的规则。1. ax1 = fig.add_subplot(121, projection='3d') #作用:在画布(fig)上创建一个3D 坐标系的子图,用于绘制 3D 图形。projection='3d' 是关键参数,指定这个子图是3D 坐标系(默认是 2D) # 具体来说,121 拆分为三个数字: # 第一个数字 1:表示整个画布被分成 1 行; # 第二个数字 2:表示整个画布被分成 2 列; # 第三个数字 1:表示当前子图是这 1×2 网格中的第 1 个位置(从左到右、从上到下计数)。 ax1=fig.add_subplot(121,projection='3d') #取行号全取,【1,0】【2,0】【3,0】 c: color green ax1.scatter(X[:,0], X[:,1], X[:,2], c='g') # 作用:在创建的 3D 子图(ax1)中绘制3D 散点图,展示数据的三维分布。 # 逐参数解析: # X[:,0]:取数组 X 中所有行的第 0 列数据(第一个特征),作为 3D 空间中的x 轴坐标; # X[:,1]:取数组 X 中所有行的第 1 列数据(第二个特征),作为 3D 空间中的y 轴坐标; # X[:,2]:取数组 X 中所有行的第 2 列数据(第三个特征),作为 3D 空间中的z 轴坐标; ax1.scatter(X[:,0],X[:,1],X[:,2],c='g') ax1.set_title('Before PCA(3D)') ax1.set_xlabel('Feature 1') ax1.set_ylabel('Feature 2') ax1.set_zlabel('Feature 3') #转换后的二维可视化 #转换3维数据可视化 fig=plt.figure(figsize=(12,4)) #三维数据 ax1=fig.add_subplot(122) # 122 是 matplotlib 中用于指定子图位置的参数,遵循 “行数 × 列数 × 索引” 的规则,具体含义是: # 第一个数字 1:表示整个画布被分成 1 行; # 第二个数字 2:表示整个画布被分成 2 列; # 第三个数字 2:表示当前子图是这个 1行2列 网格中的第 2 个位置(从左到右依次计数) ax1.scatter(X_pca[:,0],X_pca[:,1],c='g') ax1.set_title('After PCA(2D)') ax1.set_xlabel('Principal Component 1') ax1.set_ylabel('Principal Component 2') plt.show()定义主成分方向向量,直接按照n个数据, 标准正态分布,需要知道谁是第一主成分,第二主成分(根据方差判断)
模型评估和模型选择(重点)
损失函数
第四种,适用于比如,算概率啥的 -似然函数
本质:函数的值与真实数据带来的误差
针对损失函数的推导
一元线性回归的正规方程
一元的推导没有问题,
我的理解是先对k进行偏导,然后b的偏导
但是里面x的i次幂和kx的i次幂相乘应该是 2i,这块是图片的一个小错误
下面的是对k求导

对b求导,同理
两个方程联立求解
多元线性回归的正规方程


x的转置*x =| |x| | 2^2 等于2范数向量的模长,每个元素平方求和,再开平方根
正规方程法-> 一步步求导
如果运算量过大,可能会造成内存溢出
假设矩阵没有逆,则可能无解
经验误差

欠拟合与过拟合
拟合指机器学习模型,在训练数据上学习规律,并且声称预测结果的过程。
面对新数据,也有好的表现,即模型有良好的泛化能力
这两种的根本原因就是:模型复杂度过低/过高,导致测试误差(泛化误差偏大)
欠拟合:模型在训练集和测试集上误差都比较大,模型过于简单,高偏差(模型复杂度)(开始两个误差都特别大,此时就是欠拟合)
过拟合:模型在训练集上误差较小,但是测试集上误差比较大,模型过于复杂,高方差(学的太细了,会迅速减小,然后到某一点开始上升了)
欠拟合
- 模型复杂度不足,过于简单,无法捕捉数据中复杂关系
- 特征不足:输入特征不充分,或者特征选择不恰当,导致模型无法充分学习数据的模式(如果X是一个向量,他的是一行特征数量太少了)
- 训练不充分:训练过程迭代次数太少,模型没有足够的时间学习数据的规律
- 过强的正则化:正则化项设置过大,强制模型过于简单,导致模型无法充分拟合数据(正则化:使模型变简单的东西)
解决方法
- 增加模型复杂度,选择较复杂的模型
- 增加特征或改进特征工程:添加更多的特征或通过特征工程来创造更有信息量的特征
- 增加训练时间:增加训练的迭代次数,让模型有更多机会去学习
- 减少正则化强度:如果使用了正则化,尝试减少正则化权重,让模型跟灵活。
过拟合
- 模型复杂度过高:模型过于复杂,参数太多
- 训练数据不足:数据集太小,模型能记住训练数据的细节,但是无法泛化到新数据
- 特征过多:特征太多,模型可能会记住数据中的噪声,并非学到真正的规律
- 训练过长,训练时间过长,导致模型学习到训练数据中的噪声,而非数据的真正规律
解决方法
- 减少模型复杂度:降低模型的参数数量,使用简化的模型或降维来减小模型复杂度
- 增加训练数据:收集更多数据,或通过数据增强来增加训练数据的多样性
- 使用正则化:引入L1,L2正则化,避免过度拟合训练数据
- 交叉验证:使用交叉验证技术评估模型在不同数据集上的表现,以减少过拟合的风险
- 早停:训练时,当模型的验证损失不再下降时候,提前停止训练,避免过度拟合训练集
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression #线性回归模型
from sklearn.preprocessing import PolynomialFeatures #构建多项式特征
from sklearn.model_selection import train_test_split #划分训练集和测试集
from sklearn.metrics import mean_squared_error #平方(均方)误差损失函数 mse
'''
1.生成数据
2.划分训练集和测试集(验证集)
3.定义模型(线性回归模型)
4.训练模型
5.预测结果,计算误差
'''
#生成数据,基于sin(x)+误差 大致按照sin(x)
'''
reshape(-1, 1)
1 表示转换后数组的列数固定为 1(即变成 “单列”);
-1 是一个 “通配符”,表示 “行数由系统自动计算”(总元素数 ÷ 列数 = 行数)。
这里总元素数是 300,列数是 1,因此行数 = 300 ÷ 1 = 300,最终形状为 (300, 1)(300 行,1 列的二维数组)
'''
X=np.linspace(-3,3,300).reshape(-1,1) #起始点,结束点,和多少个点 ,reshape:我只要求她排成一列
y=np.sin(X)+np.random.uniform(low=-0.5,high=0.5,size=300).reshape(-1,1) #添加一个随机噪声
print(X.shape)
print(y.shape)
#画出散点图(3个子图)
fig,ax=plt.subplots(1,3,figsize=(15,4))
#2.划分训练集和测试集(验证集)
# ax[0].scatter(X, y, c='y') 的具体含义是:
# 在第 1 个子图(ax[0])上绘制散点图;
# X 是点的 x 轴坐标(横轴数据);
# y 是点的 y 轴坐标(纵轴数据);
# c='y' 设定点的颜色为黄色('y' 是 'yellow' 的缩写)。
ax[0].scatter(X,y,c='y')
ax[1].scatter(X,y,c='y')
ax[2].scatter(X,y,c='y')
# plt.show()
#2.划分训练集和测试集(验证集) ->
'''
X:特征数据(如你生成的 X,形状 (300, 1));
y:标签数据(如你生成的 y,形状 (300, 1));
test_size=0.2:指定测试集占总数据的比例(这里是 20%),因此训练集占 80%(300×80%=240 个样本,测试集 60 个样本);
random_state=42:随机数种子(固定值 42 保证每次运行划分结果完全相同,便于复现实验)
'''
trainX,testX,trainY,testY=train_test_split(X,y,test_size=0.2,random_state=42)
#3.定义模型(线性回归模型)
model = LinearRegression()
#一、欠拟合(直线)
x_train1=trainX
x_test1=testX
#4.训练模型 fit适配,适应的意思
model.fit(x_train1,trainY)
#打印查看模型参数 . coef:系数 =斜率
print(model.coef_)
print(model.intercept_) # intercept: 截距
#5.预测结果,计算误差
# predict 方法会根据模型训练学到的规律
# (即 model.coef_ 系数和 model.intercept_ 截距),对 x_test1 中的每个样本计算预测值;
y_pred1=model.predict(x_test1) #测试数据代入进去
test_loss1=mean_squared_error(testY,y_pred1) #传递两个参数,预测值和真实值 ,前面真实值,后面预测值
train_loss1=mean_squared_error(trainY,model.predict(x_train1)) #训练误差
#画出拟合曲线,并写出训练误差和测试误差
# 作用:在第 1 个子图(ax[0])上绘制模型的预测曲线。
# 逐参数解析:
# X:x 轴数据(与散点图的 x 轴一致,即原始特征数据);
# model.predict(X):模型对X的预测结果(y 轴数据,是根据模型学到的规律计算出的预测值);
# 'r':指定曲线颜色为红色('r'是'red'的缩写)。
# 对于线性回归模型,这会画出一条直线(因为线性模型的预测结果是线性关系),用于展示模型对数据趋势的拟合情况。
ax[0].plot(X,model.predict(X),'r')
# 作用:在第 1 个子图(ax[0])上添加文本标签,显示模型的测试误差。
# 逐参数解析:
# -3:文本在 x 轴上的位置(横坐标);
# 1:文本在 y 轴上的位置(纵坐标);
# f"测试误差: {test_loss1}":要显示的文本内容,其中{test_loss1}会被替换为实际的测试误差值(比如均方误差 MSE)。
# 这样可以在图上直接标注模型性能指标,方便直观对比不同模型的效果(比如后续对比多项式回归时,能一眼看出哪个模型误差更小)。
ax[0].text(-3,1,f"测试误差: {test_loss1:.4f}")
ax[0].text(-3,1.3,f"训练误差: {train_loss1:.4f}")
plt.rcParams['font.sans-serif'] = ['Heiti TC'] # 对应 Hei.ttf,黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# plt.show()
#二、恰好拟合(5次多项式)
# PolynomialFeatures(degree=5) 是 scikit-learn(Python 机器学习库)中的一个类,用于生成多项式特征,主要作用是将原始特征映射为更高阶的多项式组合特征。
# 其中 degree=5 是核心参数,表示要生成5 阶多项式特征。
# 具体来说,假设原始数据有特征 [x1, x2],当 degree=5 时,会生成以下几类特征:
# 所有 1 阶特征:x1, x2
# 所有 2 阶特征:x1², x1x2, x2²
# 直到 5 阶的所有可能组合(包括不同特征的乘积和单个特征的幂)
poly5=PolynomialFeatures(degree=5) #degree:最高次,就是5次项 0次项就是常数项
# transform() 的作用是将拟合好的多项式特征转换规则应用到原始数据上。
# 具体来说:
# 首先 poly5.fit(trainX) 会分析训练数据 trainX,确定多项式特征的生成规则(比如根据指定的阶数 5,计算出所有可能的特征组合方式)
# 然后 transform(trainX) 会按照这个规则,将原始的 trainX 数据转换为新的多项式特征矩阵 x_train2
# 例如,如果原始数据是单一特征 [x1],经过 5 阶多项式转换后,会生成包含 [x1, x1², x1³, x1⁴, x1⁵] 等特征的新矩阵。
x_train2=poly5.fit_transform(trainX)
x_test2=poly5.fit_transform(testX)
print(x_train2.shape) #0.8划分 240
print(x_test2.shape) #0.2测试集划分 60
#4.训练模型
model.fit(x_train2,trainY)
#打印查看模型参数
#5.预测结果,计算误差
y_pred2=model.predict(x_test2)
test_loss2=mean_squared_error(testY,y_pred2)
train_loss2=mean_squared_error(trainY,model.predict(x_train2))
#画出拟合曲线,并写出训练误差和测试误差
#应该传递的值是高次项的参数
ax[1].plot(X,model.predict(poly5.fit_transform(X)),'r')
ax[1].text(-3,1,f"测试误差:{test_loss2:.4f}")
ax[1].text(-3,1.3,f"训练误差:{train_loss2:.4f}")
#三、过拟合
# PolynomialFeatures(degree=5) 是 scikit-learn(Python 机器学习库)中的一个类,用于生成多项式特征,主要作用是将原始特征映射为更高阶的多项式组合特征。
# 其中 degree=5 是核心参数,表示要生成5 阶多项式特征。
# 具体来说,假设原始数据有特征 [x1, x2],当 degree=5 时,会生成以下几类特征:
# 所有 1 阶特征:x1, x2
# 所有 2 阶特征:x1², x1x2, x2²
# 直到 5 阶的所有可能组合(包括不同特征的乘积和单个特征的幂)
poly5=PolynomialFeatures(degree=20) #degree:最高次,就是5次项 0次项就是常数项
# transform() 的作用是将拟合好的多项式特征转换规则应用到原始数据上。
# 具体来说:
# 首先 poly5.fit(trainX) 会分析训练数据 trainX,确定多项式特征的生成规则(比如根据指定的阶数 5,计算出所有可能的特征组合方式)
# 然后 transform(trainX) 会按照这个规则,将原始的 trainX 数据转换为新的多项式特征矩阵 x_train2
# 例如,如果原始数据是单一特征 [x1],经过 5 阶多项式转换后,会生成包含 [x1, x1², x1³, x1⁴, x1⁵] 等特征的新矩阵。
x_train3=poly5.fit_transform(trainX)
x_test3=poly5.fit_transform(testX)
print(x_train3.shape) #0.8划分 240
print(x_test3.shape) #0.2测试集划分 60
#4.训练模型
model.fit(x_train3,trainY)
#打印查看模型参数
#5.预测结果,计算误差
y_pred3=model.predict(x_test3)
test_loss3=mean_squared_error(testY,y_pred3)
train_loss3=mean_squared_error(trainY,model.predict(x_train3))
#画出拟合曲线,并写出训练误差和测试误差
#应该传递的值是高次项的参数
ax[2].plot(X,model.predict(poly5.fit_transform(X)),'r')
ax[2].text(-3,1,f"测试误差:{test_loss3:.4f}")
ax[2].text(-3,1.3,f"训练误差:{train_loss3:.4f}")
plt.show()
这块,其实我有个问题,为什么5阶就是差不多正好,5阶是什么意思是泰勒展开吗,我去问AI ,他的意思是,5阶多项式,他去自动给你寻找最合适的参数
这个问题抓得特别准!核心结论是:5 阶不是 sinx 的 5 阶泰勒展开,而是 5 阶多项式特征转换,只是它的复杂度刚好匹配 sinx + 噪声的数据规律。
一、先明确:5 阶的本质是 “多项式特征”,和 sinx 展开无关
代码里的
degree=5,是PolynomialFeatures的参数,含义是 “生成最高 5 次的多项式特征”,和 sinx 的泰勒展开没有直接关联:
- 5 阶多项式特征:对原始特征 X,生成
[1, X, X², X³, X⁴, X⁵]的特征组合(默认含偏置项 1),模型是线性回归拟合这些特征的线性组合(比如y = a0 + a1X + a2X² + ... + a5X⁵)。- sinx 的 5 阶泰勒展开:是
sinX ≈ X - X³/6 + X⁵/120,是特定的 5 次多项式形式,但代码里的 5 阶多项式没有限定这个系数规律,模型会自动学习最优系数。简单说:一个是 “不限定系数的 5 次多项式模型”,一个是 “固定系数的 5 次多项式近似”,二者是两回事。
二、为什么 5 阶刚好拟合?核心是 “复杂度匹配”
数据的真实规律是
sinX + 噪声,sinX 是光滑的非线性函数,而不同复杂度的模型对它的拟合能力不同:
- 线性模型(1 阶):只能画直线,无法捕捉 sinX 的弯曲趋势,所以欠拟合。
- 5 阶多项式:复杂度适中,既能弯曲足够多次来贴合 sinX 的波动,又不会过度纠结噪声。
- 20 阶多项式:复杂度太高,会 “绕着” 每个数据点弯曲,把噪声当成真实规律,所以过拟合。
这里的 “刚好” 是实验结果 —— 不是 5 阶天生适合 sinX,而是这个数据场景下,5 阶多项式的表达能力刚好匹配数据的非线性复杂度。

引入: 假如某一个参数不重要,我们给他干掉,是否可以呢,比如直接20阶,但是系数可以是0 ,那么把20次方,直接弄没。---------- 正则化
正则化
训练模型时候,损失函数中添加额外项,来惩罚过大的参数,从而限制模型复杂度,避免过拟合,提高泛化能力技术。
前面是平方损失函数,叠加起来/n (x,y一直,f(x)里面的系数不知道,所以后面加上一个所有系数的平方和,假如系数越大,越多,则损失多大,但是后面的系数很多的话,可以让前面的系数变小)
我的理解:
是不是说,正则化,会让我过拟合,测试训练数据的时候,也没那么好的表现,这样,就会减少训练数据和测试数据的区别
正则化的核心作用就是通过 “牺牲一点训练表现” 来大幅提升测试表现,从而缩小训练和测试的差距,本质是在 “拟合能力” 和 “泛化能力” 之间找平衡。
可以用一个通俗的逻辑拆解:
- 过拟合时,模型在训练数据上表现极好(把噪声当规律死记硬背),但测试数据上表现极差(因为没学到通用规律),训练和测试的差距很大。
- 加入正则化后,模型会被 “约束”,不能无限制地拟合训练数据的细节(包括噪声),因此训练表现会略有下降,但它被迫去学习更通用的规律,从而测试表现会大幅提升。最终训练和测试的差距就被缩小了。
举个例子:
- 过拟合的模型:训练损失 0.01,测试损失 2.0(差距 1.99)。
- 加正则化后:训练损失 0.1(略有上升),测试损失 0.3(大幅下降),差距缩小到 0.2。
所以正则化不是 “让模型变弱”,而是 “让模型放弃对噪声的过拟合,转而学习真正的规律”,最终实现训练和测试表现的统一。
L1正则化,L2正则化
L1正则化(Lasso回归)
可以通过惩罚模型参数的绝对值,使得部分权重趋紧于0甚至变成0,这会导致特征选择,即特征会自动"丢弃"一些不重要的特征,正则化有助于创建稀疏模型(即很多参数为0)
λ超参数控制着正则化的强度,较大的λ值,意味着强烈的正则化,会使模型更加简单,可能导致欠拟合。而较小的λ值 会使模型更加复杂,从而导致过拟合
L2正则化(Ridge回归 岭回归)
L2可以惩罚模型参数的平方,使所有参数都变的更小,但不会强行将参数强行压缩为0,会使模型尽量平滑,从而防止过拟合
双方的wi都是代表参数 ,多项式的参数
ElasticNet正则化(弹性网络回归)
梯度下降法
梯度方向:函数变化增长最快的方向(变量沿着这个方向变化时候,函数增长最快,贪心)
负梯度方向:函数变化减少最快的方向(变量沿着此方向变化时候函数减少最快)
下一步的参数值,基于上一个参数值,更新,倒三角-表示梯度
损失函数求梯度,本身是一个向量函数/梯度函数
步子很小,收敛很慢,但是假如很大也是越过极小值点,会反复横跳。
特点:
- 梯度下降不一定找到全局最优解,可能是局部最优
- 优点:适用性广泛,计算简单
- 缺点:收敛速度慢,有可能陷入局部最优 (最好是下坡函数 y=x^2那种 U型)
分类:
批量梯度下降(BGD) - 每次迭代使用全部训练数据计算梯度
- 优点:稳定内敛
- 缺点:计算开销大
随机梯度下降(SGD) - 每次迭代随机选取一个样本计算梯度
- 优点:速度快,适合大规模数据
- 缺点:梯度更新方向不稳定,优化过程震荡比较大,可能难以收敛。
小批量梯度下降 - 每次迭代使用一小批样本,如(32,64个)计算梯度
- 平衡了BGD和SGD的速度,是最常用的方法
梯度下降法计算步骤
- 初始化参数: 随机选择初始参数
- 计算梯度: 在当前参数在,计算损失函数的梯度
- 更新参数: 沿负梯度方向调整参数
- 重复迭代: 直到满足停止条件(如梯度接近零,达到最大迭代次数)
import numpy as np import matplotlib.pyplot as plt def f(x): return x**2 #定义梯度函数(导函数) def gradient(x): return 2*x #用列表保存点的变化轨迹 x_list=[] y_list=[] #定义超参数和x的初始值 alpha=0.1 x=1 #重复迭代100次 for i in range(100): y=f(x) #记录当前点的坐标 x_list.append(x) y_list.append(y) print(f"x={x},f(x)={y}") #当前计算梯度 grad=gradient(x) #更新参数 x=x-alpha*grad #画图 x=np.arange(-1,1,0.01) plt.plot(x,f(x)) plt.plot(x_list,y_list,"r") plt.scatter(x_list,y_list,color="r") plt.show()
#案例2: 使用复杂案例 f(x)=x^2 x为何值时候,f(x)=2 使用人的思想是代数求值 #机器的思想,我可以让f(x)=(f(x)-2)^2 ->(x^2 -2)^2的最小值,因为他的最小值为0,所以当他为0的时候,f(x)=2 import numpy as np import matplotlib.pyplot as plt def J(x): return (x**2-2)**2 #定义梯度函数(导函数) def gradient(x): return 4*x**3-8*x # -> 2(x^2-2)*2x-> 4x^3- 8x x_list=[] y_list=[] #定义超参数和x的初始值 alpha=0.1 x=1 # 重复迭代:终止条件,达到最大的迭代次数,梯度接近于0 (导数为0,取极值点) while np.abs(grad:= gradient(x))>1e-10: y=J(x) #我理解这两个就是统计他的点,然后记录这俩的多值 x_list.append(x) y_list.append(y) print(f"x={x},J(x)={y}") #更新参数 x=x-alpha*grad print(len(x_list)) #画图 ,我们在这个图可以看到,第一个点和下面的点是不在一起,密集点都在下面那一段,所以我们选择忽略第一个点,选择观看其他的,我们看下面的那些密集的点 x=np.arange(1,1.6,0.01) plt.plot(x,J(x)) plt.plot(x_list,y_list,"r") plt.scatter(x_list,y_list,color="r") plt.show() #局部放大 x=np.arange(1,1.6,0.01) fig,ax=plt.subplots(1,2,figsize=(15,4)) ax[0].plot(x,J(x)) ax[0].plot(x_list,y_list,"r") ax[0].scatter(x_list,y_list,color="r") x_list2=x_list[1:] y_list2=y_list[1:] x=np.arange(1.399,1.425,0.001) ax[1].plot(x,J(x)) ax[1].plot(x_list2,y_list2,"r") ax[1].scatter(x_list2,y_list2,color="r") plt.show()
L1正则化的梯度理解(较复杂)
求梯度,这里不好理解,一个是他的对w求导
sign其实就是,用来让wi 求导时候,表示为正还是为负

这句话半天没理解,问了一上午豆包。




读到这里,我们理解这个正则化的作用了
那么来理解稀疏性
首先到这,理解了为什么会稳定在0,那么理解什么是稀疏性
L2正则化梯度理解




模型评价指标
对学习的泛化性能进行评估,不仅需要有效可行的实验估计方法,还需要有衡量模型泛化能力的评价指标,也叫性能度量
回归模型评价指标
模型的评价指标用于衡量模型在训练集或者测试集上的性能,评估结果反映了模型预测的准确性和泛化能力
对于回归问题,最常用的性能度量是 “均方误差 ”(Mean Squared Error MSE)
R^2(决定系数)
衡量模型对目标变量的解释能力,越接近1越好,对异常值敏感。 如果下面越大,那么允许上面的也会越大
分类模型评价指标

对于分类问题,最常用的指标是正确率,即分类器对测试集正确分类的样本数与总样本书之比。 正确/总
我的理解,就跟那个核酸,我有可能误监测,有可能真检测到了为真/假
实现混淆矩阵
import pandas as pd from sklearn.metrics import confusion_matrix import seaborn as sns #定义类别标签 labels=["猫","狗"] #定义数据(预测值和真实值) y_true = ["猫", "猫", "猫", "猫", "猫", "猫", "狗", "狗", "狗", "狗"] # 真实值 y_pred = ["猫", "猫", "狗", "猫", "猫", "猫", "猫", "猫", "狗", "狗"]# 预测值 跟案例相同 #得到混淆矩阵 matrix=confusion_matrix(y_true, y_pred, labels=labels) print(matrix) #index代表行标签 col:列标签 print (pd.DataFrame(matrix,columns=labels, index=labels))
#使用热力图 sns.heatmap(matrix, annot=True, fmt="d",cmap="Greens")
准确率(Accuracy)
from sklearn.metrics import accuracy_score accuracy=accuracy_score(y_true, y_pred) #真实值,预测值 print(accuracy)精确率(Precision)
预测为正例对样本中为正例的比例,也叫查准率
from sklearn.metrics import precision_score precision=precision_score(y_true, y_pred, pos_label="狗") print(precision)召回率(Recall)
实际为正类的样本中,预测为正类的比例,也叫查全率
from sklearn.metrics import recall_score recall=recall_score(y_true, y_pred,pos_label="猫") print(recall)F1分数(F1 score)
from sklearn.metrics import f1_score f1=f1_score(y_true,y_pred,pos_label="猫") print(f1)
代码中,可以通过sklearn.metrics.classification_report生成分类任务的评估报告,包括精确率,召回率,F1分数等。
from sklearn.metrics import classification_report
report=classification_report(y_true,y_pred,labels=labels,target_names=None)
print(report)
support 总共的数量,预测的准确率
macro avg宏平均 宏平均 把上面的各个加起来求平均值
weighted avg:根据所有样本里面这一类加权平均,比如0.77*0.6+0.57*0.4

逻辑回归->用来做分类
逻辑回归之所以能用于生成分类评估报告,核心原因是它本质上是一种分类模型,能够输出样本属于某个类别的预测结果(或概率),而分类评估报告正是基于这些预测结果与真实标签的对比来生成的
import pandas as pd import numpy as np from sklearn.datasets import make_classification #创建一个适用于分类数据集的函数 from sklearn.metrics import classification_report #用于生成分类评估报告 from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression #逻辑回归分类模型 #生成数据 1000*20的矩阵 ,n_classes分类个数 X,y=make_classification(n_samples=1000,n_features=20,n_classes=2,random_state=42) print(X.shape) print(y.shape) #1000个数据,有1000个标签 #2.划分数据集 测试数据0.3 训练数据0.7 1000个一共 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) #3.定义一个分类模型(逻辑回归) model = LogisticRegression() #4.模型训练 model.fit(X_train, y_train) #5.进行预测,做测试集 y_pred=model.predict(X_test) #6.生成分类评估报告 report=classification_report(y_test,y_pred) print(report)
ROC曲线

ROC曲线(Receiver Operating Characteristic Curve,受试者工作特征)是评估二分类模型性能的工具,以假正例率(FPR)为横轴,以真正例率(TPR)为纵轴,展示不同阈值下模型的表现。绘制ROC曲线时,从高到低调整阈值,计算每个阈值的TPR和FPR并绘制所有阈值的点,形成ROC曲线
TPR 和 FPR 本质上是两个独立计算的指标,只是在阈值变化时会呈现出一定的联动关系,而阈值为 0 的极端情况正好凸显了这一点。
人工画图ROC



基于ROC提出AUC
AUC代表ROC曲线的面积,用于量化性能,AUC值越大,模型区分正负能力越强,模型的性能越好,AUC值=0.5表示模型接近随机猜测,AUC值=1代表完美模型。(100%不误判)
sklearn.metrics.roc_auc_score计算
接着前面的代码
#获取预测正类的概率值 y_pred=model.predict_proba(X_test)[:,1] #前后为1, 后面为正列 # print(y_pred) # 计算auc值 from sklearn.metrics import roc_auc_score roc_auc=roc_auc_score(y_test,y_pred) print(roc_auc)
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

加入随机噪声,模型的表现应该差一点(模型越差,特征就越重要-本身的添加了相同的噪声
)

















































所有评论(0)