机器学习02-特征工程
前言:
上一节学习了sklearn库的安装以及各类数据集的加载与下载,包括数据集的划分(二维数组数据集划分(train_test_split)和字典数据集划分(DictVectorizer),以及一点fit_transform函数的应用。本节将学习特征工程,对于fit_transform函数有更深入的学习,以及提取字典DictVectorizer特征和统计词频CountVectorizer的方法原理以及应用,以及TF-IDF,一种常用的文本特征表示方法的学习。
可能会用到的模块:
- import numpy as np(引用一些数学公式)
- from sklearn.feature_extraction import DictVectorizer(提取字典特征信息)
- from sklearn.feature_extraction.text import CountVectorizer(统计词频)
- from sklearn.feature_extraction.text import TfidfVectorizer(计算TF-IDF的API方法)
- from sklearn.preprocessing import normalize(计算归一化)
一、特征工程
1、特征工程API即说明
-
特征工程的目的就是为了再训练模型之前处理数据,让数据变得更好一点,让训练出来的模型效果更好。
-
处理数据的方案:
-
特征的提取:提取数据集中的信息,进行数据信息的转化,如果遇到缺失值、异常值需要进行处理。
-
归一化处理:把数据集中数值压缩在一定范围,避免大值数据这种异常值的影响,可以消除掉数据中的单位因素产生的影响。
-
标准化处理:把数据集变成均值为x,标准差为y这样的分布,机器学习提供的API满足均值为0,标准差为1。(默认情况)
-
降维处理:去掉数据集中一些不需要的特征信息,这些信息
-
-
常用的 API 如下:
| 名称 | 作用 |
|---|---|
| DictVectorizer | 字典特征提取 |
| CountVectorizer | 文本特征提取 |
| TfidfVectorizer | TF-IDF 文本特征词的重要程度特征提取 |
| MinMaxScaler | (最大值、最小值)归一化 |
| StandardScaler | 标准化 |
| VarianceThreshold | 低方差过滤降维 |
| PCA | 主成分分析降维 |
-
常用方法和功能介绍如下:
| 函数名 | 参数 | 作用 |
|---|---|---|
| fit(list_of_dicts) | 一个包含字典的列表 | fit方法用来计算数据的统计信息,比如训练集的均值,方差,最大值,最小值等,只要fit之后,如果存在多个数据(比如 train、test)需要transform,可以直接transform |
| transform(list_of_dicts) | 一个包含字典的列表 | transform 方法根据fit方法所学习到的参数来转换数据。这可能意味着标准化特征,填充缺失值,编码类别变量等 |
| fit_transform(list_of_dicts) | 一个包含字典的列表 | fit和transform两个方法的合成(和先执行fit方法再执行transform方法的两行代码等价) |
| get_feature_names_out() | 列表 | 返回一个包含所有特征名称的列表,这些特征是在 fit 或 fit_transform 方法中学习到的 |
| inverse_transform(X) | fit_transform生成 | 将特征矩阵转换回原来的字典形式 |
2、DictVectorizer字典特征提取
-
DictVectorizer是sklearn.feature_extraction中用于提取特征和编码的重要工具之一,特别适用于处理字典格式的数据。它可以将字典列表转换为模型可以直接使用的数值型特征矩阵(每一行代表一个样本,每一列代表一个特征) -
DictVectorizer实例化参数:参数 默认值 说明 dtypenumpy.float64输出数组的数据类型 separator"="当类别特征名称与值之间需要拼接时使用(默认不启用) sparseTrue如果为 True,输出是三元组的稀疏矩阵;如果为False,输出是 Numpy 数组(以下案例输入True)sortTrue是否按字母顺序排序特征名 -
提取为稀疏矩阵:具体行列可见6.3
-
fit_transform方法等价于先执行fit方法,再执行transform方法。
-
注意:
-
我们训练模型的时候只能够提供训练集里面的信息给fit方法,不能提供测试模型里的信息给fit方法,否则会导致测试集中的数据已经被fit方法处理了,模型后期做验证的时候就会存在误差。
-
训练数据集fit之后,就不需要对测试集进行fit方法了,测试集是直接使用训练集里的信息(最大值、最小值...)
-
-
代码:
from sklearn.feature_extraction import DictVectorizer import numpy as np """ DictVectorizer不会处理数字,数字是多少处理后就是多少 如果是字符串,就会处理,不同字符产就会作为不同的特征 每一个特征就是一列数据,这一列数据满足一个位置上的数值是1,其余位置为0 """ #定义一个数据集 data=[ {"name":"张三","address":"成都","age":18}, {"name":"李四","address":"上海","age":19}, {"name":"王五","address":"广州","age":20}, ] #床架字典特征提取的对象 dv=DictVectorizer(sparse=True)#sparse=True提取的是稀疏矩阵 result=dv.fit_transform(data) #上面这个代码和下面两行代码是等价的 # dv.fit(data) # result=dv.transform(data) print(result) #查看特征名称(会警告) # print(dv.get_feature_names())# FutureWarning: Function get_feature_names is deprecated; get_feature_names is deprecated in 1.0 and will be removed in 1.2. Please use get_feature_names_out instead.warnings.warn(msg, category=FutureWarning) #加上out就好了 print(dv.get_feature_names_out()) #输出结果 print(type( result))#<class 'scipy.sparse.csr.csr_matrix'> #转为numpy的ndarray数组类型 result2=result.toarray() print(f"result2:{type(result2)}") #转为numpy的matrix类型 result3=result.todense() print(f"result3:{type(result3)}") -
输出结果:
DictVectorizer() (0, 2) 1.0 (0, 3) 18.0 (0, 4) 1.0 (1, 0) 1.0 (1, 3) 19.0 (1, 5) 1.0 (2, 1) 1.0 (2, 3) 20.0 (2, 6) 1.0
-
3、CountVectorizer
-
CountVectorizer是一个在自然语言处理(NLP)任务中常用的工具,用于将文本数据转换为向量形式。它属于sklearn.feature_extraction.text模块的一部分。CountVectorizer主要通过词汇表构建、词频统计、输出格式的方式进行工作。并且最终输出的是一个稀疏矩阵(每一行对应一个文档,每一列对应词汇表中的一个词。矩阵中的每个元素表示某个词在某个文档中出现的次数。) -
作用:统计各个词语在各自的文本中出现的次数
-
CountVectorizer实例化参数:
| 参数名 | 类型 | 默认值 | 描述说明 |
|---|---|---|---|
stop_words |
string 或 list | None |
指定要忽略的停用词集合:<br> - 若设为 'english',则会使用内建的英语停用词列表(如 "is", "the" 等)<br> - 也可以传入一个自定义的停用词列表<br> - 单个字母(如 "i"、"a")通常会被自动忽略 |
lowercase |
bool | True |
是否在分词前将文本统一转换为小写:<br> - 设为 True:自动转换为小写(推荐用于英文文本)<br> - 设为 False:保留原始大小写格式 |
1、提取英文文本
-
countVectorizer创建出来的对象可以实现统计词语的次数,也可以对英文进行分词操作。
-
提取英文文本需要的参数:
-
导入CountVectorizer函数:
from sklearn.feature_extraction.text import CountVectorizer -
进行词频统计:
cv.fit_transform() -
转换输出类型为numpy数组:
toarray() -
获取特征名称(防止报错加上out):
cv.get_feature_names_out()
-
-
案例代码
#导入需要的包:pandas、sklearn import pandas as pd from sklearn.feature_extraction.text import CountVectorizer #创建数据集 documents = [ 'This is the first document.', 'This document is the second document.', 'And this is the third one.', 'Is this the first document?', 'this is an apple.' ] #创建对象(并进行词频统计) cv=CountVectorizer() result=cv.fit_transform(documents) #将输出的稀疏矩阵转换为numpy数组 print(result.toarray()) -
输出结果:
[[0 0 0 1 1 1 0 0 1 0 1] [0 0 0 2 0 1 0 1 1 0 1] [0 1 0 0 0 1 1 0 1 1 1] [0 0 0 1 1 1 0 0 1 0 1] [1 0 1 0 0 1 0 0 0 0 1]] -
为了更直观的观察数据,我获取了特征名称,使用了pandas库中的DataFrame函数,具体代码如下:
print(cv.get_feature_names_out()) df=pd.DataFrame(result.toarray(),columns=cv.get_feature_name_out()) print(df) -
输出结果:
['an' 'and' 'apple' 'document' 'first' 'is' 'one' 'second' 'the' 'third' 'this'] an and apple document first is one second the third this 0 0 0 0 1 1 1 0 0 1 0 1 1 0 0 0 2 0 1 0 1 1 0 1 2 0 1 0 0 0 1 1 0 1 1 1 3 0 0 0 1 1 1 0 0 1 0 1 4 1 0 1 0 0 1 0 0 0 0 1
2、提取中文文本
-
因为英文文本的提取不需要考虑短语,只需要通过英文之间本身的空格进行分词即可,而中文之间没有空格,就需要用到jieba进行中文文本的分词。
-
jieba是一个广泛使用的中文分词库,并支持三种分词模式:
-
默认模式(精确模式):一般默认选择这种模式,按照词典对文本进行分词。
-
全模式:细粒度更高的分词,分词的结果会更多一点
-
搜索引擎模式:在精确模式的基础上,把长一点的词汇进一步的分词。
-
-
安装jieba分词库:
pip install jieba -i https://pypi.mirrors.ustc.edu.cn/simple/
1、基础分词
-
案例1代码:
data="中国是一个伟大的国家,中国是一个好的国家,中国是一个好的国家" #默认模式 result1=jieba.lcut(data) print("精确模式:",result1) #全模式 result2=jieba.lcut(data,cut_all=True) print("全模式:",result2) #搜索引擎模式 result3=jieba.lcut_for_search(data) print("搜索引擎模式:",result3) -
结果输出:
精确模式: ['中国', '是', '一个', '伟大', '的', '国家', ',', '中国', '是', '一个', '好', '的', '国家', ',', '中国', '是', '一个', '好', '的', '国家'] 全模式: ['中国', '国是', '一个', '伟大', '的', '国家', ',', '中国', '国是', '一个', '好', '的', '国家', ',', '中国', '国是', '一个', '好', '的', '国家'] 搜索引擎模式: ['中国', '是', '一个', '伟大', '的', '国家', ',', '中国', '是', '一个', '好', '的', '国家', ',', '中国', '是', '一个', '好', '的', '国家']
2、添加词典
-
创建一个txt文件。在文件中,每一行就是一个词,一共有三个数据:词、词频、词性。加载自定义的词典,使用方法load_userdict实现,参数就是词典的访问路径。(这里只写了词频)
-
例如
呜呜的响 100 吹进 100000000(这里吹进词频设置得很大是为了防止一些自定义的词没法被应用)
-
案例代码:
data = """我冒了严寒,回到相隔二千余里,别了二十余年的故乡去。 时候既然是深冬;渐近故乡时,天气又阴晦了,冷风吹进船舱中,呜呜的响, 从篷隙向外望,苍黄的天底下,远近横着几个萧索的荒村,没有一些活气。 我的心禁不住悲凉起来了。""" #引入自定义的词典 jieba.load_userdict("./my_dict") #进行分词 result=jieba.lcut(data) print( "/".join(result)) -
结果输出:
我/冒/了/严寒/,/回到/相隔/二千余/里/,/别/了/二十余年/的/故乡/去/。/ / / / / /时候/既然/是/深冬/;/渐近/故乡/时/,/天气/又/阴晦/了/,/冷风/吹进/船舱/中/,/呜呜的响/,/ / / / / /从篷隙/向/外望/,/苍黄/的/天底下/,/远近/横着/几个/萧索/的/荒村/,/没有/一些/活气/。/ / / / / /我/的/心/禁不住/悲凉/起来/了/。 -
(因此输出的分词结果会有我们自己设定的词典里的词,比如“呜呜的响”和“吹着”)
3、词性标注
-
jieba可以结合posseg模块进行词性标注
-
常见的词性
| 标签 | 含义 | 标签 | 含义 | 标签 | 含义 | 标签 | 含义 |
|---|---|---|---|---|---|---|---|
| n | 普通名词 | f | 方位名词 | s | 处所名词 | t | 时间 |
| nr | 人名 | ns | 地名 | nt | 机构名 | nw | 作品名 |
| nz | 其他专名 | v | 普通动词 | vd | 动副词 | vn | 名动词 |
| a | 形容词 | ad | 副形词 | an | 名形词 | d | 副词 |
| m | 数量词 | q | 量词 | r | 代词 | p | 介词 |
| c | 连词 | u | 助词 | xc | 其他虚词 | w | 标点符号 |
| PER | 人名 | LOC | 地名 | ORG | 机构名 | TIME |
-
案例代码:
import jieba.posseg as pseg words = pseg.cut("我爱北京天安门") for word, flag in words: print(f'{word} {flag}') -
运行结果:
我 r 爱 v 北京 ns 天安门 ns
4、停用词
-
如果你想去掉无意义的词(如的、是),可以使用停用词表
-
案例代码:
import jieba text = "你和我是好朋友的吧" stopwords = set(["的", "是", "和"]) words = jieba.lcut(text) print("未使用停用词:", words) words1 = [w for w in jieba.cut(text) if w not in stopwords] print("使用停用词:", words1) -
运行结果:
未使用停用词: ['你', '和', '我', '是', '好', '朋友', '的', '吧'] 未使用停用词: ['你', '和', '我', '是', '好', '朋友', '的', '吧']
4、TF-IDF
-
TF-IDF是词频-逆文档频率,描述的是一个词在一个文本的重要程度。是一种常用的文本特征表示方法。比如如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力(适合用来分类)
-
词频(Frequency):一个词在语料库中出现的次数,词频越高,说明该词在该文档中越重要
-
词频概率(Word Probability): 通常指的是归一化后的词频,即一个词在文档中出现的次数除以文档总词数,用来衡量这个词在整个文档中的相对重要性,如下公式:
词在文档中出现的次数文档中词的总数
-
逆文档频率(IDF):词语在整个文档集合中的重要程度。
-
TF-IDF:是词频(TF)和词频概率(IDF)两个指标的乘积,两个部分的具体计算公式如下:
-
TF:=CountVectorizer(统计的结果)
-
IDF:文档总数包含该词语的文件的数目数
-
TF-IDF:
-
-
TfidfVectorizer 是 scikit-learn 提供的一个工具,用于将文本数据转换为 TF-IDF 特征矩阵,函数介绍如下:
| 参数名 | 类型 | 默认值 | 描述说明 |
|---|---|---|---|
stop_words |
string 或 list | None |
指定要忽略的停用词集合:<br> - 若设为 'english',则会使用内建的英语停用词(如 "is", "the" 等)<br> - 也可以传入一个自定义的停用词列表<br> - 单个字母(如 "i"、"a")通常会被自动忽略 |
use_idf |
bool | True |
是否启用 IDF(逆文档频率)加权:<br> - 设为 True:使用 TF-IDF 权重计算<br> - 设为 False:仅使用 TF(词频)并归一化 |
smooth_idf |
bool | True |
是否对 IDF 进行平滑处理:<br> - 加1平滑,防止除以0的情况,使计算更稳定 |
norm |
string | 'l2' |
归一化方式:<br> - 'l1':L1 范数归一化(所有特征绝对值之和为1)<br> - 'l2':L2 范数归一化(默认,欧氏距离归一化) |
(注意:它的数学公式和机器学习提供的函数方法存在一些区别,如IDF在机器学习中的函数公式会在各个分量上都加上1,以防分量出现为零的情况。)
-
计算过程:
-
1、得到所有为一次与按字典序排序。
-
2、第二步【这个步骤之后的每个步骤都以文档一为例】:计算词频 TF,得到向量表示形式:
[0, 1, 1, 1, 0, 0, 1, 0, 1]
词 出现次数 and 0 document 1 first 1 is 1 one 0 second 0 the 1 third 0 this 1 -
3、计算逆文档频率 IDF
词 出现在哪些文档 出现文档数 IDF 计算 IDF 值(保留4位小数) and d3 1 log(4+1/(1+1)) + 1 ≈ log(5/2) + 1 ln(2.5) + 1 ≈ 1.9163 document d1, d2, d4 3 log(4+1/(3+1)) + 1 = log(5/4) + 1 ln(1.25) + 1 ≈ 1.2231 first d1, d4 2 log(4+1/(2+1)) + 1 ≈ log(5/3) + 1 ln(1.6667) + 1 ≈ 1.5108 is d1, d2, d4 3 log(4+1/(3+1)) + 1 ≈ log(5/4) + 1 ln(1.25) + 1 ≈ 1.2231 one d3 1 log(4+1/(1+1)) + 1 ≈ log(5/2) + 1 ln(2.5) + 1 ≈ 1.9163 second d2 1 log(4+1/(1+1)) + 1 ≈ log(5/2) + 1 ln(2.5) + 1 ≈ 1.9163 the d1, d2, d3, d4 4 log(4+1/(4+1)) + 1 ≈ log(5/5) + 1 ln(1.0) + 1 = 1.0000 third d3 1 log(4+1/(1+1)) + 1 ≈ log(5/2) + 1 ln(2.5) + 1 ≈ 1.9163 this d1, d2, d4 3 log(4+1/(3+1)) + 1 ≈ log(5/4) + 1 ln(1.25) + 1 ≈ 1.2231 -
4、计算 TF-IDF
词 TF IDF TF-IDF(= TF × IDF) and 0 1.9163 0 document 1 1.2231 1.2231 first 1 1.5108 1.5108 is 1 1.2231 1.2231 one 0 1.9163 0 second 0 1.9163 0 the 1 1.0000 1.0000 third 0 1.9163 0 this 1 1.2231 1.2231 -
5、L2归一化(默认norm='l2')

-

| 词 | TF-IDF | 归一化后值(保留4位小数) |
|---|---|---|
| and | 0.0000 | 0.0000 |
| document | 1.2231 | 0.4388 |
| first | 1.5108 | 0.5420 |
| is | 1.2231 | 0.4388 |
| one | 0.0000 | 0.0000 |
| second | 0.0000 | 0.0000 |
| the | 1.0000 | 0.3587 |
| third | 0.0000 | 0.0000 |
| this | 1.2231 | 0.4388 |
1、API方法
-
案例代码:
#导入类 from sklearn.feature_extraction.text import TfidVectorizer #创建数据集 data = [ 'This is the first document', 'This is the second document', 'And the third one', 'Is this the first document', ] #创建对象 tf=TfidVectorizer() #进行词频统计 result=tf.fit_transform(data) #输出结果并将稀疏矩阵转换为numpy数组 print(result.toarray()) #输出特征信息 print(tf.get_feature_names_out())
5、无量纲化
-
在机器学习中,无量纲化是一种非常重要的数据预处理方法。它的主要目的是将不同量纲、不同数量及的特征统一到一个相对可比的范围内,以提高模型的性能和稳定性。
-
常见的无量纲化方法:
| 方法名称 | 原理 | 公式 | 特点 |
|---|---|---|---|
| 归一化(Min-Max Scaling) | 将数据缩放到 [0,1] 区间 | | 保留原始分布形状,对异常值敏感 |
| 标准化(Z-Score Scaling) | 数据服从正态分布时使用 | | 不受极值影响,适用于大多数模型 |
| 最大绝对值缩放(MaxAbs Scaling) | 缩放到 [-1,1],保持原符号 | | 不会改变数据的稀疏性,并且不会移动或居中数据 |
| L2 归一化(向量单位化) | 每个样本向量除以它的 L2 范数 | | 常用于文本、图像等嵌入向量 |
5.1MinMaxScaler归一化
-
最大最小归一化是一种线性变换过程,使得数据按照一定的规则重新映射到一个特定的范围,通常是 (0, 1)。(就是通过缩放的方式,把值缩放在一定范围之内,从而减少了因为不同特征之间的单位的影响。)
-
作用:去掉数据中单位不同的影响(这种操作一般需要使用在有数据范围边界的情况下)。
-
通过下面的方式实现:(按照每一列:特征(axis=0)进行计算)
-
和分别是原始数据集中的最小值和最大值
-
表示当前需要归一化的值:
-
MinMaxScaler:是一种用于归一化数据的技术,通常用于机器学习和数据分析中。MinMaxScaler是sklearn.preprocessing模块中的一个类,可以方便地应用于数据集,MinMaxScaler()用来实例化对象,参数如下:
参数名 类型 默认值 说明 feature_rangetuple (min, max) (0, 1)指定缩放的目标范围,默认是 [0, 1]。也可以设置为其他范围,例如 (−1, 1)copyboolean True是否复制原始数据(避免修改原始数据)。如果为 False,则尝试进行原地操作(in-place) -
-
列表数据集案例代码:
from sklearn.preprocessing import MinMaxScaler
from sklearn.feature_extraction import DictVectorizer
# 数据准备(5个数据(每行一条数据),2个特征(每列一个特征))
data = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
# 创建对象
nms = MinMaxScaler()
result = nms.fit_transform(data)
print(result)
-
结果输出:
[[0. 0. ]
[0.25 0.25]
[0.5 0.5 ]
[0.75 0.75]
[1. 1. ]]
-
字典数据集案例代码:
from sklearn.preprocessing import MinMaxScaler
from sklearn.feature_extraction import DictVectorizer
# 数据集准备---字典数据
data= [
{"name": "张三", "address": "成都", "age": 18},
{"name": "李四", "address": "上海", "age": 19},
{"name": "王五", "address": "广州", "age": 20},
]
# 创建对象
dv = DictVectorizer()
nms=MinMaxScaler()
result = dv.fit_transform(data)
print(dv.get_feature_names_out())
print(result.toarray())
# 归一化
rs=nms.fit_transform(result.toarray())
print( rs)
-
结果输出:
['address=上海' 'address=广州' 'address=成都' 'age' 'name=张三' 'name=李四'
'name=王五']
[[ 0. 0. 1. 18. 1. 0. 0.]
[ 1. 0. 0. 19. 0. 1. 0.]
[ 0. 1. 0. 20. 0. 0. 1.]]
[[0. 0. 1. 0. 1. 0. 0. ]
[1. 0. 0. 0.5 0. 1. 0. ]
[0. 1. 0. 1. 0. 0. 1. ]]
-
总结:
-
归一化的目的是为了消除不同特征值之间量级上的差异,从而避免因不同特征值的范围差异对模型训练产生不良影响。
-
""" 数学公式: result=(X-Xmin)/(Xmax-Xmin) 默认范围[0,1] API:from sklearn.preprocessing import MinMaxScaler 参数:feature_range=(0,1)---缩放过后的值的范围 解决问题:如果数据集中存在异常,比如数据1 1 2 3 4突然来了一个数字1000,那么就会导致其他的数据被压缩在接近于0的位置 每一个特征之间,进行单独的计算,即以每一列进行最大值和最小值统计计算 """ -
不适合用于具有无限或开放边界的数据,如果你的数据在未来可能会出现比训练集更大或更小的值(比如实时更新的传感器数据),使用
MinMaxScaler缩放后的值可能会超出 [0, 1] 范围,造成不稳定。
-
5.2normalize归一化
-
在机器学习中,Normalize(归一化) 是一种对样本向量进行单位化的操作,而不是像
MinMaxScaler那样对特征列进行缩放,normalize是按行(样本)方向进行单位化的。(就是将每个样本的特征向量除以它的范数(norm),使得该向量的长度变为 1) -
作用:常用于更加关注向量之间的方向差异(如余弦相似度),而非大小的场景,比如文本分类、图像检索、推荐系统等任务中
-
参数说明:
| 参数名 | 类型 | 默认值 | 含义 |
|---|---|---|---|
X |
array-like of shape (n_samples, n_features) | - | 输入数据(二维数组或稀疏矩阵) |
norm |
{'l1', 'l2', 'max'}, default='l2' | 'l2' |
使用哪种范数来归一化 |
axis |
int, default=1 | 1 |
归一化的方向:<br>1:按行(每个样本)<br>0:按列(每个特征) |
copy |
boolean, default=True | True |
是否复制原数据(避免修改原始输入) |
return_norm |
boolean, default=False | False |
是否返回每个样本的范数值 |
-
返回值
| 参数设置 | 返回值类型 | 返回值说明 |
|---|---|---|
return_norm=False(默认) |
ndarray 或 sparse matrix |
归一化后的数据(每个样本单位化) |
return_norm=True |
(X_normalized, norms) |
一个元组:<br>1. 归一化后的数据<br>2. 每个样本对应的范数值 |
利用范数来实现数据的无量纲化
"""
范数:
l1:
数学公式:rs=||x||/(||x1||+...+||xn||) #每一条数据的值的和为1
l2:
数学公式:rs=||x||/sqrt(||x1||^2+...+||xn||^2) #每一条数据的值的平方和的平方根为1
l∞:
数学公式:rs=max(X,1) #每一条数据中,最大的值的结果为1
API: from sklearn.preprocessing import normalize
normalize(X,norm="l2",*,axis=1,copy=True,return_norm=False)
参数:
X:输入数据
norm:选择的番薯:l2,l1,max
axis:按照每一行进行数据处理
"""
-
代码:
from sklearn.preprocessing import normalize
#导入数据集
data=[[1,2,3],[4,5,6],[7,8,9]]
l1=normalize(data,norm="l1",axis=1)
print(l1)
print("====================================")
l2=normalize(data,norm="l2",axis=1)
print(l2)
print("====================================")
max=normalize(data,norm="max",axis=1)
print(max)
print("====================================")
-
输出结果:
[[0.16666667 0.33333333 0.5 ]
[0.26666667 0.33333333 0.4 ]
[0.29166667 0.33333333 0.375 ]]
====================================
[[0.26726124 0.53452248 0.80178373]
[0.45584231 0.56980288 0.68376346]
[0.50257071 0.57436653 0.64616234]]
====================================
[[0.33333333 0.66666667 1. ]
[0.66666667 0.83333333 1. ]
[0.77777778 0.88888889 1. ]]
====================================
-
总结:
-
L1 范数适合稀疏数据、L2 范数适合强调方向一致性、Max 范数适合强调最大特征影响。要根据任务目标来选择最合适的归一化方式,才能提升模型性能。
5.3标准化
-
在机器学习中,标准化是一种数据预处理技术,也称为数据归一化或特征缩放。它的目的是将不同特征的数值范围缩放到统一的标准范围,以便更好地适应一些机器学习算法,特别是那些对输入数据的尺度敏感的算法。(就是把所有的值按照均值为0,标准差为1分布)
-
去中心化:每一个值减去均值。
-
公式如下:
-
z 是转换后的数值
-
x 是原始数据的值
-
μ 是该特征的均值
-
σ 是该特征的标准差
-
参数求解:
-
-
属性和方法:
| 特性/属性/方法 | 说明 |
|---|---|
| 所属模块 | sklearn.preprocessing |
| 主要功能 | 对数据进行标准化(零均值、单位方差) |
| 标准化公式 | <br>其中 μ 是均值,σ 是标准差 |
| 常用方法 | |
.fit(X) |
计算每个特征的均值和标准差 |
.transform(X) |
使用计算出的均值和标准差对数据进行标准化 |
.fit_transform(X) |
先调用 fit,再调用 transform |
.inverse_transform(X) |
将标准化后的数据还原为原始分布 |
| 参数设置 | |
with_mean=True |
是否中心化(每一个数据减去均值),默认 True |
with_std=True |
是否缩放(除以标准差),默认 True |
| 输入数据类型支持 | list, numpy.ndarray, pandas.DataFrame |
| 输出数据类型 | numpy.ndarray |
| 与 MinMaxScaler 区别 | |
| 标准化 vs 归一化 | StandardScaler:基于均值和标准差<br>MinMaxScaler:将数据缩放到 [0,1] 区间 |
| 对异常值敏感度 | StandardScaler 对异常值较敏感 |
| 适用场景 | 当数据近似服从正态分布时效果较好 |
-
案例代码:
#导入标准化类
from sklearn.preprocessing import StandardScaler
#导入数据集
data=[[1,2],[3,4],[5,6]]
#创建对象
ss=StandardScaler()
#训练模型
result=ss.fit_transform(data)
#结果
print( result)
print("=================================")
#均值
print(ss.mean_)
print("=================================")
#标准差
print(ss.scale_)
print("=================================")
-
结果输出:
[[-1.22474487 -1.22474487]
[ 0. 0. ]
[ 1.22474487 1.22474487]]
=================================
[3. 4.]
=================================
[1.63299316 1.63299316]
=================================
(标准化是按照特征每一列来进行处理的,也是在划分数据集之后进行。)
5.4归一化和标准化对比
| 对比维度 | 标准化(Standardization) | 归一化(Normalization) |
|---|---|---|
| 目的 | 将数据转换为均值为 0,标准差为 1 的分布 | 将数据缩放到一个特定范围(如 [0,1] 或 [-1,1]) |
| 常用方法/类 | sklearn.preprocessing.StandardScaler |
sklearn.preprocessing.MinMaxScaler<br>sklearn.preprocessing.MaxAbsScaler<br>sklearn.preprocessing.Normalizer |
| 公式 | <br>(z-score 标准化) | |
| 对异常值的敏感度 | 较高(因为依赖于均值和标准差) | 较低(依赖最小最大值,受极端值影响大但不如标准化明显) |
| 输出范围 | 不固定,可能有负值 | 默认在 [0,1] 区间(也可自定义) |
| 是否适用于分布偏态较大的数据 | 不太适合(除非是为了去中心化->即让均值为0) | 相对更合适(尤其当数据分布不规则时) |
| 适用模型 | 基于距离的模型(如 KNN、SVM、PCA、线性回归等) | 梯度下降优化算法、神经网络、图像处理、文本向量归一化 |
| 是否保留原始分布形状 | 是(只是进行了平移和缩放) | 否(强制压缩到某个区间) |
总结
归一化、标准化操作都是放在划分数据集操作之后进行。因为训练模型之前,是不能够泄露测试数据集信息的,否则会导致测试不准确。(这个思想要扩展到后期训练模型)
6、数据转换器的三大方法
-
fit(X):在训练集上使用
-
transform(X):应用于训练集之外的数据(如验证集、测试集、新样本)
-
fit_transform(X):在训练集上使用(推荐方式)
-
代码展示:
#导入标准化类
from sklearn.preprocessing import StandardScaler
#导入划分数据集包
from sklearn.model_selection import train_test_split
# 假设 X 是原始特征数据,y 是标签
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
# ✅ 正确做法
# 步骤1:在训练集上拟合并转换(fit + transform)
X_train_scaled = scaler.fit_transform(X_train)
# 步骤2:仅转换测试集(使用训练集的统计信息)->fit一次后直接transform即可,不需要再fit了,可接多个transform
X_test_scaled = scaler.transform(X_test)
# ❌ 错误:在测试集上重新 fit,导致模型“看到”测试集信息
scaler.fit(X_test)
X_test_scaled = scaler.transform(X_test)
# ❌ 错误:在测试集上调用 fit_transform,也会污染训练过程
X_test_scaled = scaler.fit_transform(X_test)
7、特征降维
-
目的:去掉数据集中对于模型进行数据识别等操作影响几乎不大的特征信息,减少维度,比如 300 维度变成 100 维度,从而提高计算效率,减少这些没必要的特征信息的影响。
-
方法:
-
低方差过滤法:就是计算某个特征的方差,如果方差小于我们手动设置的阈值,就舍弃掉这个方差。
-
相关系数法:计算特征与目标变量之间的相关性系数,选择高相关的特征。
-
主成分分析(PCA):就是把某一个高维度的特征信息投影到低维度上。
-
-
好处:
-
减少计算成本:降维可以简化模型,降低训练时间和资源需求。
-
去除噪声:
-
过拟合:在模型训练过程中,在训练数据集中不仅学到了很好的特征信息(需要模型识别的内容),还学习到了背景等噪声信息,这样的模型会影响其鲁棒性。这样的模型在已知的数据集中(训练数据集)可以很好的预测结果,但是对于一个新的数据样本,就无法做出很好的预测了。
-
欠拟合:在模型训练过程中,训练出来的模型效果差(训练集表现差、未知数据样本表现差)。一般情况,发生这样的问题就是数据集的问题、训练次数不够,模型没有得到最佳值。
-
-
7.1低方差过滤法
-
举例解释:
-
假设我们正在做一个项目,目的是区分两种猫:英国短毛猫(英短)和美国短毛猫(美短)。我们收集了一些数据,其中包括以下几个特征:
-
体重(单位:千克)
-
体长(单位:厘米)
-
是否有两个眼睛(是/否)
-
-
假设数据
猫品种 体重 体长 是否有两个眼睛 英短 4.5 50 是 英短 4.7 52 是 英短 4.6 51 是 美短 5.0 55 是 美短 5.1 56 是 美短 5.0 55 是 -
方差分析和计算:
特征 均值 μ 总体方差 是否可被过滤? 原因说明 体重 ≈ 4.8167 ≈ 0.0514 否 存在一定差异,对模型有用 体长 ≈ 53.1667 ≈ 5.1389 否 差异明显,区分度高 是否有两个眼睛 1 0 ✅ 是 所有值相同,无法帮助模型做区分 -
总结
-
方差小(接近0):如上述例子,对于“是否有两个眼睛”这一特征,方差为0。这是因为所有猫都有两只眼睛,该特征对于区分不同种类的猫是没有帮助的。
-
方差大:“体重”和“体长”的方差大,这意味着这些特征在不同种类的猫之间有所不同,因此可以用来区分猫的品种。
-
-
-
实现步骤:
-
准备数据:准备需要过滤特征的数据集。
-
计算方差:计算每个特征的方差,可以使用 Pandas 的
var()方法。 -
设定阈值:设定一个阈值来确定哪些特征的方差过低。这个阈值通常是根据数据的具体情况和业务需求来设定的。如果方差低于这个阈值,则认为该特征的变异程度太低,可以考虑移除。
-
过滤特征:使用 scikit-learn 中的
VarianceThreshold类来移除方差低于指定阈值的特征。 -
查看结果:查看经过低方差过滤后的特征数量,并确认哪些特征被移除了。
-
-
函数介绍:
| 项目 | 内容说明 |
|---|---|
| 所属模块 | sklearn.feature_selection |
| 类名 | VarianceThreshold |
| 作用 | 实现低方差过滤的特征选择方法,用于删除那些在样本中变化很小的特征 |
| 适用场景 | 特征值几乎不变(如所有样本都为1或0)的特征可被移除 |
| 原理 | 计算每个特征的方差,若方差小于设定阈值,则认为该特征对模型无帮助,删除它 |
| 参数名 | threshold,float 类型,默认值 0.0,设置方差阈值。只有方差大于等于该值的特征才会保留,低于该值的特征将被删除 |
-
案例代码:
#导入导入低方差过滤类
from sklearn.feature_selection import VarianceThreshold
#导入鸢尾花数据集
from sklearn.datasets import load_iris
import pandas as pd
#导入鸢尾花数据
iris=load_iris()
data,target=iris.data,iris.target#取鸢尾花的数据和标签
#输出前两个数据
print(data[:2])
#提取特征信息
print(iris.feature_names)
#计算方差(通过pandas方法var)
df=pd.DataFrame(data,columns=iris.feature_names)
std=df.var()
print(std)
#创建低方差过滤对象---阈值设置
vt=VarianceThreshold(threshold=0.5)
result=vt.fit_transform(data)
print(result[:2])
-
结果输出:
[[5.1 3.5 1.4 0.2]
[4.9 3. 1.4 0.2]]
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
sepal length (cm) 0.685694
sepal width (cm) 0.189979
petal length (cm) 3.116278
petal width (cm) 0.581006
dtype: float64
[[5.1 1.4 0.2]
[4.9 1.4 0.2]]
7.2相关系数法
-
正相关性:
-
在正相关的关系中,两个变量的变化趋势是同向的,当两个变量正相关时,一个增加,另一个很大概率也会增加,减少同理。
-
-
负相关性:
-
与正相关的关系相反,但是变量也是相关的,比如运动频率和BMI体重指数就是呈负相关。
-
-
不相关:
-
不相关并不表示完全不相关,而是两者的相关性很小,一个变量变化不会引起另一个变量的变化,没有线性关系,比如饭量和智商。
-
-
协方差:
-
协方差是反映了这两个变量在这一点上是否一起“偏高”或“偏低”它们各自的平均水平。
-
如果协方差为正:表示两个变量同方向变化
-
如果协方差为负:表示两个变量反方向变化
-
如果协方差接近0:说明两者之间没有明显的线性关系
-
-
样本协方差计算公式:
-
-
每一对数据点相对于它们各自平均值的偏差乘积之和:
-
:表示第 i 个 x 值相对于所有 x 的平均值的“偏离”
-
:表示第 i 个 y 值相对于所有 y 的平均值的“偏离”
-
它们的乘积:反映了这两个变量在这一点上是否一起“偏高”或“偏低”
-
-
(
numpy.cov()是numpy中用于计算协方差矩阵的重要函数,广泛应用于统计分析、机器学习、数据科学等领域。)-
协方差案例代码:
import numpy as np x = np.array([2, 4, 5, 6, 8]) y = np.array([65, 75, 80, 85, 95]) cov_matrix = np.cov(x, y) print("协方差矩阵:") print(cov_matrix) print("x 和 y 的协方差:", cov_matrix[0, 1]) 运行结果: 协方差矩阵: [[ 5. 25.] [ 25. 125.]] x 和 y 的协方差: 25.0
-
-
-
皮尔逊相关系数:
-
相关系数r及相关强度:
相关系数 r 范围 相关性强度描述 r=1 完全正相关 0.7<r<1 强正相关 0.4<r<0.7 中度正相关 0.1<r<0.4 弱正相关 r=0 无相关 −0.1<r<0 弱负相关 −0.4<r<−0.1 中度负相关 −0.7<r<−0.4 强负相关 r=−1 完全负相关 
-
函数介绍:
-
函数参数
参数名 类型 必须相同长度 描述 x一维数组(array-like) 是 第一个变量数据(如学习时间、身高等) y一维数组(array-like) 是 第二个变量数据(如考试成绩、体重等),必须与 x长度一致-
返回值
返回值 类型 描述 correlationfloat 皮尔逊相关系数,取值范围 [-1, 1]:<br> - 1:完全正相关<br> 0:无线性关系<br> -1:完全负相关 pvaluefloat 假设检验的 p 值,用于判断相关性是否显著:<br> - p < 0.05:相关性显著<br>( - p ≥ 0.05:不显著 -
-
案例代码:
#皮尔逊相关系数 from scipy.stats import pearsonr #学习时间 x=np.array([1,2,3,4,5]) #考试成绩 y=np.array([2,4,6,8,10]) #计算皮尔逊相关系数 """ 相关系数:描述的是x y之间的相关性 p值:描述的是是否肯定原假设(x y 之间不相关) p<0.05:否定假设 p>0.05:肯定假设 """ correlation,pvalue=pearsonr(x,y) print('Pearson相关系数:',correlation) print('Pearson p值:',pvalue)#输出的p值<0.05表示否定假设(x y之间不相关),即x y之间相关。
-
结果输出:
-
Pearson相关系数: 1.0
Pearson p值: 0.0
7.3PCA
-
主成分分析(Principal Component Analysis,PCA)是一种用于降维的技术,核心目标是从原始特征空间中找到一个新的坐标系统,使得数据在新坐标轴上的投影能够最大程度地保留数据的方差(方差越大,数据越离散,得到的信息量就越大),同时减少数据的维度。(把高维度的信息使用低维度来表示)
-
通过 PCA 降维,可以使用较少的数据维度,保留住最多的原始数据特征,这个就是第一主成分,当然还存在其他主成分,但是出现在 F1 中的信息不能出现在其他主成分中,比如第二主成分,那么就需要让和独立,即协方差为 0,
-
为了达到降维的目的,PCA 提供了两种方式优化:
-
最大可分性:*样本投影到低维度平面后,要尽可能的分散(方差最大)
-
最近重构性:*样本到所投影的低维度平面的距离,要尽可能的小(让所有样本点的这些垂直距离平方和最小)(b^2=a^2+c^2,c表示数据点a投影在L上离原点的距离;a表示数据点投影在)
-
原理
-
假设在二维坐标中有一个点 a(x‘,y’) ,(x‘,y’) 描述的就是 a 点的两个特征信息,如何把 a 点的两个特征信息在直线 L 上表示出来?

-
通过数学变化可以得到 a(x',y') 坐标信息在 L 上的投影分别为
投影到的大小投影到的大小
-
使用 (x',y') 表示一个点,该点有两个特征, 而映射到 L 上用一个特征就可以表示这个点了。这就达到了降维的功能
-
投影到 L 上的值就是降维后的保留信息,投影到与 L 垂直的轴上的值就是丢失的信息
信息保留的比例保留信息原始信息
-
下图中红线上点与点的距离是最大的,所以在红色线上点的方差最大,粉红线上的刚好相反。所以用红色线上点来表示之前点的信息,信息损失是最小的

-
(要保证方差越大,即投影的点要分散,所以选择上图中的橘色线来进行投影)
-
PCA:是sklearn.decomposition中的一个类,用来实现主成分分析,PCA(n_components=None)方法用来实例化对象的参数如下:
n_components 类型 |
含义说明 | 公式/说明 |
|---|---|---|
| 小数(0 < k < 1) | 表示希望保留原始数据信息的百分比(即解释方差比) | 假设我们有特征值 ,则信息保留比可以表示为,其中是选择的主成分的数量,是原始数据的特征数量 |
| 整数(k) | 表示直接选择前 k 个主成分 | 只保留前 k 个主成分 |
-
案例代码:
#导入PCA类
from sklearn.decomposition import PCA
#导入鸢尾花数据
from sklearn.datasets import load_iris
#导入鸢尾花数据
iris=load_iris()
data,target=iris.data,iris.target
#创建PCA对象
pca=PCA(n_components=0.95)#需要保留原来特征信息的95%
result=pca.fit_transform(data)
print(result[:2])
pca1=PCA(n_components=3)#需要保留3个特征信息
result1=pca1.fit_transform(data)
print(result1[:2])
-
结果输出:
[[-2.68412563 0.31939725]
[-2.71414169 -0.17700123]]
[[-2.68412563 0.31939725 -0.02791483]
[-2.71414169 -0.17700123 -0.21046427]]
-
总结:
"""
PCS:主成分分析,就是利用把高维度的信息映射到低维度上,用低维度特征取描述高维度特征。
API:from sklearn.decomposition import PCA
参数:n_components
1、小数形式:
需要保留多少原特征信息,是一个百分比---这里会根据需要保留的信息去选择多少个维度来描述。
2、整数形式:
需要保留的多少个特征信息,比如原来有4个特征信息,如果设置为3,救国就保留3个特征信息。
"""
更多推荐



所有评论(0)