机器学习day02

特征工程

特征工程是机器学习项目中的一个重要环节,它的目标是从原始数据中提取出有用的特征,以便让机器学习模型能够更好地理解和预测数据。简单来说,特征工程就像是给机器学习模型准备好“食材”,让它能够做出美味的“菜肴”。
为什么需要特征工程?
在机器学习中,模型的表现很大程度上取决于数据的质量。有时候,原始数据并不直接适用于模型训练,需要经过一定的加工和转换。特征工程就是这个加工过程,它可以帮助我们从数据中挖掘出更有价值的信息,从而提高模型的性能。
特征工程的步骤
数据清洗:
清理数据中的错误和缺失值。
比如,去除重复的数据记录,填补缺失的值。
特征选择:
从原始数据中挑选出对预测最有帮助的特征。
有时候原始数据中有许多特征,但并不是每一个都对预测有用,甚至有些特征还可能引入噪声。
特征构造:
根据业务知识和经验创造新的特征。
例如,如果原始数据中包含了日期,我们可以从中提取出月份、星期几等新特征。
特征转换:
将原始特征转换成更适合模型的形式。
比如,将类别型特征(如颜色、性别等)转换成数值型特征,或者对数值型特征进行归一化处理。
特征降维:
减少特征的数量,同时尽量保留重要的信息。
这有助于减少模型的复杂度,防止过拟合。
总结
特征工程就像是一位厨师在烹饪之前精心挑选和准备食材一样,通过对原始数据进行一系列的加工和转换,使得最终的模型能够更好地理解和利用这些数据。通过特征工程,我们可以确保机器学习模型接收到的是最优质、最相关的“食材”,从而做出准确的预测。

所以下面内容都是讲解如何处理原始数据

1、DictVectorizer字典列表特征提取

什么是字典列表特征提取?

字典列表特征提取是指从一系列字典组成的列表中提取特征,并将其转换成机器学习算法可以使用的数值型数据的过程。这些字典通常包含了一些非数值型的数据,比如类别型特征(如城市名、颜色等)和数值型特征(如温度、价格等)。

为什么要进行字典列表特征提取?

在机器学习中,大多数算法只能处理数值型数据。因此,我们需要将非数值型的数据转换成数值型的数据,这样才能让算法正确地工作。

如何进行字典列表特征提取?

准备数据:

数据通常是一系列字典,每个字典代表一个样本,字典的键代表特征名称,值代表特征的取值。

使用 DictVectorizer:

DictVectorizer 是一个工具,它可以从字典列表中提取特征,并将这些特征转换成数值型的数据。
它会分析字典中的键,确定所有可能的特征,并为每个特征创建一个列。

转换数据:

对于每个样本(即每个字典),DictVectorizer 会根据特征列表创建一个特征向量。
如果某个特征在样本中出现,那么在对应的特征向量中,该特征的位置会被标记为 1(或者具体的数值);如果没有出现,则标记为 0。

#首先,你需要导入 DictVectorizer 类
from sklearn.feature_extraction import DictVectorizer
#实例化 DictVectorizer 创建一个 DictVectorizer 对象,你可以指定一些参数来控制转换行为,例如是否返回稀疏矩阵(默认为稀疏矩阵):稀疏矩阵即大部分元素都为0的矩阵。
dict_vec = DictVectorizer(sparse=False)  # 设置 sparse=False 返回密集矩阵
#拟合和转换数据 使用 fit_transform 方法来拟合数据并转换数据 这里的 data 是一个字典列表,每个字典代表一个样本,字典的键代表特征名称,值代表特征的取值。
X_train = dict_vec.fit_transform(data)
#你可以使用 get_feature_names_out 方法获取转换后的特征名称:
feature_names = dict_vec.get_feature_names_out()

案例:

from sklearn.feature_extraction import DictVectorizer

users_data = [
    {'name': 'Alice', 'age': 28, 'gender': 'female', 'city': 'New York', 'subscribed': True},
    {'name': 'Bob', 'age': 35, 'gender': 'male', 'city': 'Los Angeles', 'subscribed': False},
    {'name': 'Charlie', 'age': 22, 'gender': 'male', 'city': 'Chicago', 'subscribed': True},
    {'name': 'Diana', 'age': 42, 'gender': 'female', 'city': 'San Francisco', 'subscribed': True},
    {'name': 'Eve', 'age': 29, 'gender': 'female', 'city': 'Seattle', 'subscribed': False},
    {'name': 'Frank', 'age': 31, 'gender': 'male', 'city': 'Boston', 'subscribed': True},
    {'name': 'Grace', 'age': 24, 'gender': 'female', 'city': 'Houston', 'subscribed': False},
    {'name': 'Henry', 'age': 37, 'gender': 'male', 'city': 'Atlanta', 'subscribed': False},
    {'name': 'Isabella', 'age': 26, 'gender': 'female', 'city': 'Dallas', 'subscribed': True},
    {'name': 'Jack', 'age': 33, 'gender': 'male', 'city': 'Miami', 'subscribed': True}
]

dv = DictVectorizer(sparse=True)
x = dv.fit_transform(users_data)
feature_names = dv.get_feature_names_out()
print(type(x))
print(x)
print(feature_names)
#稀疏矩阵对象调用toarray()函数, 得到类型为ndarray的二维稀疏矩阵 
print(x.toarray())

"""
<class 'scipy.sparse._csr.csr_matrix'>
<Compressed Sparse Row sparse matrix of dtype 'float64'
	with 50 stored elements and shape (10, 24)>
  Coords	Values
  (0, 0)	28.0
  (0, 8)	1.0
  (0, 11)	1.0
  (0, 13)	1.0
  (0, 23)	1.0
  (1, 0)	35.0
  (1, 6)	1.0
  (1, 12)	1.0
  (1, 14)	1.0
  (1, 23)	0.0
  (2, 0)	22.0
  (2, 3)	1.0
  (2, 12)	1.0
  (2, 15)	1.0
  (2, 23)	1.0
  (3, 0)	42.0
  (3, 9)	1.0
  (3, 11)	1.0
  (3, 16)	1.0
  (3, 23)	1.0
  (4, 0)	29.0
  (4, 10)	1.0
  (4, 11)	1.0
  (4, 17)	1.0
  (4, 23)	0.0
  (5, 0)	31.0
  (5, 2)	1.0
  (5, 12)	1.0
  (5, 18)	1.0
  (5, 23)	1.0
  (6, 0)	24.0
  (6, 5)	1.0
  (6, 11)	1.0
  (6, 19)	1.0
  (6, 23)	0.0
  (7, 0)	37.0
  (7, 1)	1.0
  (7, 12)	1.0
  (7, 20)	1.0
  (7, 23)	0.0
  (8, 0)	26.0
  (8, 4)	1.0
  (8, 11)	1.0
  (8, 21)	1.0
  (8, 23)	1.0
  (9, 0)	33.0
  (9, 7)	1.0
  (9, 12)	1.0
  (9, 22)	1.0
  (9, 23)	1.0
['age' 'city=Atlanta' 'city=Boston' 'city=Chicago' 'city=Dallas'
 'city=Houston' 'city=Los Angeles' 'city=Miami' 'city=New York'
 'city=San Francisco' 'city=Seattle' 'gender=female' 'gender=male'
 'name=Alice' 'name=Bob' 'name=Charlie' 'name=Diana' 'name=Eve'
 'name=Frank' 'name=Grace' 'name=Henry' 'name=Isabella' 'name=Jack'
 'subscribed']
[[28.  0.  0.  0.  0.  0.  0.  0.  1.  0.  0.  1.  0.  1.  0.  0.  0.  0.
   0.  0.  0.  0.  0.  1.]
 [35.  0.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.  1.  0.  1.  0.  0.  0.
   0.  0.  0.  0.  0.  0.]
 [22.  0.  0.  1.  0.  0.  0.  0.  0.  0.  0.  0.  1.  0.  0.  1.  0.  0.
   0.  0.  0.  0.  0.  1.]
 [42.  0.  0.  0.  0.  0.  0.  0.  0.  1.  0.  1.  0.  0.  0.  0.  1.  0.
   0.  0.  0.  0.  0.  1.]
 [29.  0.  0.  0.  0.  0.  0.  0.  0.  0.  1.  1.  0.  0.  0.  0.  0.  1.
   0.  0.  0.  0.  0.  0.]
 [31.  0.  1.  0.  0.  0.  0.  0.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.
   1.  0.  0.  0.  0.  1.]
 [24.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.  0.
   0.  1.  0.  0.  0.  0.]
 [37.  1.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.
   0.  0.  1.  0.  0.  0.]
 [26.  0.  0.  0.  1.  0.  0.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.  0.
   0.  0.  0.  1.  0.  1.]
 [33.  0.  0.  0.  0.  0.  0.  1.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.
   0.  0.  0.  0.  1.  1.]]

"""

2、CountVectorizer 文本特征提取

什么是 CountVectorizer?

CountVectorizer 是一个用于文本特征提取的工具,它主要用于将文本数据转换成数值型特征向量。这些特征向量可以被机器学习算法用来进行分类、聚类等任务。

CountVectorizer 在做什么?

CountVectorizer 的主要功能是统计文本中每个词的出现次数,并将这些计数转换成一个数值型的特征向量。简单来说,它将文本转换成了数字,这样机器学习算法就能理解和处理这些数据了。

如何使用 CountVectorizer?

实例化 CountVectorizer:

创建一个 CountVectorizer 对象,并可以设置一些参数来控制如何提取特征,比如是否忽略某些常见的词(停用词)。

拟合和转换数据:

使用 fit_transform 方法来拟合数据并将其转换成特征向量。
这个方法会自动分析文本中的词,并创建一个特征向量表头(即列名)。可以使用 get_feature_names_out 方法获取转换后的特征名称
对于每篇文本,CountVectorizer 会统计每个词的出现次数,并将这些计数填入对应的特征向量中。

texts = [
    "life is short i like python",
    "life is too short you need java",
    "i do not like java"
]

"""
将上述内容进行文本特征提取之后会得到以下内容
Feature names: ['i', 'is', 'like', 'java', 'life', 'need', 'not', 'python', 'short', 'too', 'you']
Transformed data:
[[1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0],
 [1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1],
 [1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0]]
这里的每一行代表一个文本样本,每一列代表一个词。
第一行表示第一段文本,其中 “i” 出现了 1 次,“is” 出现了 1 次,“like” 出现了 1 次,“java” 没有出现,“life” 出现了 1 次,“need” 没有出现,“not” 没有出现,“python” 出现了 1 次,“short” 出现了 1 次,“too” 没有出现,“you” 没有出现。

"""

实例:

(1)英文文本提取
from sklearn.feature_extraction.text import CountVectorizer
texts = [
    "The quick brown fox jumps over the lazy dog",
    "A quick movement of the enemy will jeopardize six gunboats",
    "The six gunboats quickly moved out of range",
    "The quick brown fox jumps over the lazy dog again",
    "A quick brown dog jumps over the lazy fox",
    "The lazy dog was very lazy and did not move",
    "The quick brown fox jumps over the lazy dog once more",
    "The quick brown fox jumps over the lazy dog yet again",
]

cv = CountVectorizer()
x = cv.fit_transform(texts)
feature_names = cv.get_feature_names_out()
print(feature_names)
print(x.toarray())

"""
['again' 'and' 'brown' 'did' 'dog' 'enemy' 'fox' 'gunboats' 'jeopardize'
 'jumps' 'lazy' 'more' 'move' 'moved' 'movement' 'not' 'of' 'once' 'out'
 'over' 'quick' 'quickly' 'range' 'six' 'the' 'very' 'was' 'will' 'yet']
[[0 0 1 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 2 0 0 0 0]
 [0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 0 1 0 0 0 1 0 0 1 1 0 0 1 0]
 [0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 1 0 0 1 1 1 1 0 0 0 0]
 [1 0 1 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 2 0 0 0 0]
 [0 0 1 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0]
 [0 1 0 1 1 0 0 0 0 0 2 0 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 0 0]
 [0 0 1 0 1 0 1 0 0 1 1 1 0 0 0 0 0 1 0 1 1 0 0 0 2 0 0 0 0]
 [1 0 1 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 2 0 0 0 1]]
"""
(2)中文文本提取

中文文本不像英文文本,中文文本文字之间没有空格,所以要先分词,一般使用jieba分词.

什么是 jieba?

jieba 是一个非常流行的中文分词库,它可以帮助我们将中文文本分割成一个个有意义的词语。简单来说,jieba 就是用来处理中文文本的一种工具,它可以把连续的汉字序列切分成一个一个的词语。

为什么需要 jieba?

在处理中文文本时,与英文不同,中文是没有明确的词与词之间的分隔符的。这意味着我们需要一种方法来识别出文本中的各个词语。jieba 就是用来解决这个问题的。

jieba 的工作原理
加载词典:

jieba 内部有一个预定义的词典,里面包含了大量常用词语。
用户也可以添加自定义的词典,以适应特定领域的分词需求。

分词:

jieba 会对输入的文本进行分词处理,将文本切分成一个个词语。
它使用了多种算法和技术来决定如何切分词语,包括基于词典的匹配、HMM(隐马尔可夫模型)等。

输出结果:

分词完成后,jieba 会返回一个包含所有词语的列表。

下面介绍以下jieba的核心函数

jieba.cut()函数

jieba.cut 是 jieba 库中最常用的分词函数之一,它可以根据不同的参数配置来进行中文文本的分词处理。

jieba.cut(sentence, cut_all=False, HMM=True)

参数说明
sentence (str):待分词的文本字符串。
cut_all (bool, 可选):控制分词模式,默认为 False。
如果 cut_all 为 False,则使用精确模式(默认模式),尽可能地返回最精确的分词结果。
如果 cut_all 为 True,则使用全模式,返回文本中所有可能的词语组合。
HMM (bool, 可选):是否使用 HMM(隐马尔可夫模型)进行分词,默认为 True。
如果 HMM 为 True,则在精确模式下使用 HMM 来识别未知词。
如果 HMM 为 False,则关闭 HMM,只使用词典进行分词。
返回值
jieba.cut 函数返回一个可迭代的对象,其中包含了分词后的结果。通常我们会将这个可迭代对象转换成列表或字符串来查看分词结果。

其他相关函数
lcut:与 cut 类似,但是返回一个列表而不是可迭代对象。

jieba使用案例:

import jieba

texts = [
    "今天天气真好",
    "今天天气真不错",
    "今天天气真差"]
list = []
for item in texts:
    list.append(" ".join(jieba.cut(item,)))
print(list)

"""
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\吃羊的草\AppData\Local\Temp\jieba.cache
Loading model cost 0.719 seconds.
Prefix dict has been built successfully.
['今天天气 真 好', '今天天气 真不错', '今天天气 真差']
"""

中文文本可以在通过jieba分词之后进行文本特征提取

案例:

import jieba
from sklearn.feature_extraction.text import CountVectorizer
texts = [
    "今天天气真好",
    "今天天气真不错",
    "今天天气真差"]
list = []
for item in texts:
    list.append(" ".join(jieba.cut(item,)))
# print(list)
cv = CountVectorizer()
x = cv.fit_transform(list)
feature_names = cv.get_feature_names_out()
print(feature_names)
print(x.toarray())

"""
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\吃羊的草\AppData\Local\Temp\jieba.cache
Loading model cost 0.717 seconds.
Prefix dict has been built successfully.
['今天天气' '真不错' '真差']
[[1 0 0]
 [1 1 0]
 [1 0 1]]
"""

3、TfidfVectorizer TF-IDF文本特征词的重要程度特征提取

什么是 TF-IDF?

TF-IDF 是一种用于衡量一个词在文档中的重要性的统计方法。它由两部分组成:
词频(Term Frequency, TF):
表示一个词在文档中出现的频率。
T F = 某个词在文章中出现的次数 / 文章的总词数 TF = 某个词在文章中出现的次数/文章的总词数 TF=某个词在文章中出现的次数/文章的总词数
词频越高,通常意味着这个词在文档中的重要性越高。
逆文档频率(Inverse Document Frequency, IDF):
表示一个词在整个文档集合中的罕见程度。
I D F = l g ( 语料库的文档总数 / 包含该词的文档数 + 1 ) IDF = lg(语料库的文档总数/包含该词的文档数+1) IDF=lg(语料库的文档总数/包含该词的文档数+1)
词的文档频率越低,其逆文档频率越高,意味着这个词在整个文档集合中越独特,因此也越重要。
TfidfVectorizer 是 scikit-learn 库中的一个工具,用于将文本数据转换为 TF-IDF 特征向量。它结合了词频和逆文档频率的概念,将文本转换为数值型特征向量。
T F − I D F = 词频 ( T F ) × 逆文档频率 ( I D F ) TF-IDF = 词频(TF)×逆文档频率(IDF) TFIDF=词频(TF)×逆文档频率(IDF)

如何使用 TfidfVectorizer

实例化 TfidfVectorizer:

创建一个 TfidfVectorizer 对象,并可以设置一些参数来控制如何提取特征,例如是否忽略某些常见的词(停用词)。

拟合和转换数据:

使用 fit_transform 方法来拟合数据并将其转换成特征向量。
这个方法会自动分析文本中的词,并创建一个特征向量表头(即列名)。
对于每篇文本,TfidfVectorizer 会计算每个词的 TF-IDF 值,并将这些值填入对应的特征向量中。

实例:
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
texts = [
    "今天吃排骨",
    "今天吃玉米",
    "今天吃鸭肉"]
list = []
for item in texts:
    list.append(" ".join(jieba.cut(item)))
print(list)
cv = TfidfVectorizer()
x = cv.fit_transform(list)
feature_names = cv.get_feature_names_out()
print(feature_names)
print(x.toarray())

"""
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\吃羊的草\AppData\Local\Temp\jieba.cache
Loading model cost 0.720 seconds.
Prefix dict has been built successfully.
['今天 吃 排骨', '今天 吃 玉米', '今天 吃 鸭肉']
['今天' '排骨' '玉米' '鸭肉']
[[0.50854232 0.861037   0.         0.        ]
 [0.50854232 0.         0.861037   0.        ]
 [0.50854232 0.         0.         0.861037  ]]
"""

4、无量纲化

无量纲化(也称为数据的标准化或规范化)是一种数据预处理技术,用于消除不同特征或指标之间的量纲差异,从而使这些特征或指标变得可比。简单来说,就是让不同单位的数据处于同一个尺度上。

为什么需要无量纲化
消除量纲影响:
不同的数据集或特征可能有不同的单位或量纲,这会导致它们之间的直接比较变得困难。
例如,一个特征是以米为单位,另一个特征是以千米为单位,如果不进行无量纲化,直接比较这两个特征的数值是没有意义的。
提高模型性能:
在机器学习中,许多算法(如支持向量机、K近邻算法、神经网络等)对数据的尺度敏感。
如果特征之间尺度相差很大,可能会导致模型偏向于那些数值较大的特征,而不是真正反映数据的内在特性。
无量纲化可以避免因特征尺度不同而导致的模型训练偏差,从而提高模型的准确性和稳定性。
简化计算:
无量纲化可以减少方程中的参数数量,简化计算过程,并使得结果更具通用性。
例如,在计算距离或相似度时,如果特征之间已经标准化,那么计算结果会更加准确可靠。

下面将介绍两种常见的无量纲化的方法

(1)MinMaxScaler归一化

通过对原始数据进行变换把数据映射到指定区间(默认为0-1)

归一化公式

归一化后的特征值 = x − m i n ( x ) / m a x ( x ) − m i n ( x ) 归一化后的特征值=x-min(x)/max(x)-min(x) 归一化后的特征值=xmin(x)/max(x)min(x)

𝑥是当前特征值

归一化示例
from sklearn.preprocessing import MinMaxScaler
import numpy as np
data = np.array([
    [100, 20],
    [150, 30],
    [200, 40]
])
scaler = MinMaxScaler(feature_range=(0, 1))
data_ = scaler.fit_transform(data)
print(data_)
"""
[[0.  0. ]
 [0.5 0.5]
 [1.  1. ]]
"""

该方法最大值和最小值容易受到异常点影响,所以鲁棒性较差。所以常使用标准化的无量纲化

(2)StandardScalar标准化

标准化公式

在这里插入图片描述

其中,z是转换后的数值,x是原始数据的值,μ是该特征的均值,σ是该特征的标准差

实例:
import numpy as np
from sklearn.preprocessing import StandardScaler
df_data = pd.read_csv("src/dating.txt")
transfer = StandardScaler()
new_data = transfer.fit_transform(df_data)
print(new_data)

"""
[[ 0.33193158  0.41660188  0.24523407  1.24115502]
 [-0.87247784  0.13992897  1.69385734  0.01834219]
 [-0.34554872 -1.20667094 -0.05422437 -1.20447063]
 [ 1.89102937  1.55309196 -0.81110001 -1.20447063]
 [ 0.2145527  -1.15293589 -1.40400471 -1.20447063]]
"""

5、特征降维

实际数据中,有时候特征很多,会增加计算量,降维就是去掉一些特征,或者转化多个特征为少量个特征

特征降维是数据预处理中的一个重要步骤,用于减少数据集中的特征数量,同时尽量保留重要的信息。以下是几种常用的特征降维方法:
主成分分析(PCA):
PCA 是一种常用的线性降维方法。它通过正交变换将原始特征转换为一组线性无关的特征,称为主成分。PCA 选择保留最大的几个主成分,从而降低了数据的维度。这种方法适用于高维数据的降维处理,能够去除冗余特征并保留重要信息。

特征选择:
特征选择是从原始特征集中挑选出最有价值的子集,以减少特征的数量。

特征降维的好处:

减少计算成本:在高维空间中处理数据可能非常耗时且计算密集。降维可以简化模型,降低训练时间和资源需求。

去除噪声:高维数据可能包含许多无关或冗余特征,这些特征可能引入噪声并导致过拟合。降维可以帮助去除这些不必要的特征。

1 .特征选择

(a) VarianceThreshold 低方差过滤特征选择

该方法用于移除数据集中方差低于某个阈值的特征。这种方法基于一个假设:方差较低的特征可能包含较少的信息,因此不太可能对模型的预测性能产生显著影响。
VarianceThreshold 的工作原理
计算特征的方差:
对于数据集中的每一个特征,计算其方差。方差是衡量特征值相对于其均值分散程度的统计量。
设定阈值:
设定一个阈值,通常是一个非负的小数值。默认情况下,VarianceThreshold 的阈值为 0,这意味着它将移除所有方差为 0 的特征。
特征选择:
保留方差大于或等于设定阈值的所有特征。
移除方差低于阈值的特征。

from sklearn.feature_selection import VarianceThreshold
import numpy as np

# 示例数据
X = np.array([
    [1, 2, 3, 4],
    [1, 2, 3, 4],
    [1, 2, 3, 4],
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [5, 6, 7, 8],
    [5, 6, 7, 8],
    [5, 6, 7, 8]
])

# 实例化 VarianceThreshold
selector = VarianceThreshold(threshold=(.8 * (1 - .8)))  # 设置阈值

# 拟合并转换数据
X_selected = selector.fit_transform(X)

# 输出选择后的特征
print("Original data shape:", X.shape)
print("Selected data shape:", X_selected.shape)
print("Selected features:")
print(X_selected)

threshold:这是一个非负浮点数,表示方差的阈值。默认值为 0,意味着移除所有方差为 0 的特征。如果设置为其他值,则会移除方差低于该值的特征。

ps:阈值的选择依赖于数据的具体情况。如果阈值设得太高,可能会丢失有用的信息;如果设得太低,则可能无法有效过滤掉噪声特征。

(b) 根据相关系数的特征选择

<1>理论

正相关性(Positive Correlation)是指两个变量之间的一种统计关系,其中一个变量的增加通常伴随着另一个变量的增加,反之亦然。在正相关的关系中,两个变量的变化趋势是同向的。当我们说两个变量正相关时,意味着:

  • 如果第一个变量增加,第二个变量也有很大的概率会增加。
  • 同样,如果第一个变量减少,第二个变量也很可能会减少。

正相关性并不意味着一个变量的变化直接引起了另一个变量的变化,它仅仅指出了两个变量之间存在的一种统计上的关联性。这种关联性可以是因果关系,也可以是由第三个未观察到的变量引起的,或者是纯属巧合。

在数学上,正相关性通常用正值的相关系数来表示,这个值介于0和1之间。当相关系数等于1时,表示两个变量之间存在完美的正相关关系,即一个变量的值可以完全由另一个变量的值预测。

举个例子,假设我们观察到在一定范围内,一个人的身高与其体重呈正相关,这意味着在一般情况下,身高较高的人体重也会较重。但这并不意味着身高直接导致体重增加,而是可能由于营养、遗传、生活方式等因素共同作用的结果。

负相关性(Negative Correlation)与正相关性刚好相反,但是也说明相关,比如运动频率和BIM体重指数程负相关

不相关指两者的相关性很小,一个变量变化不会引起另外的变量变化,只是没有线性关系. 比如饭量和智商

皮尔逊相关系数(Pearson correlation coefficient)是一种度量两个变量之间线性相关性的统计量。它提供了两个变量间关系的方向(正相关或负相关)和强度的信息。皮尔逊相关系数的取值范围是 [−1,1],其中:

  • ρ = 1 \rho=1 ρ=1 表示完全正相关,即随着一个变量的增加,另一个变量也线性增加。
  • ρ = − 1 \rho=-1 ρ=1 表示完全负相关,即随着一个变量的增加,另一个变量线性减少。
  • ρ = 0 \rho=0 ρ=0 表示两个变量之间不存在线性关系。

相关系数 ρ \rho ρ的绝对值为0-1之间,绝对值越大,表示越相关,当两特征完全相关时,两特征的值表示的向量是

在同一条直线上,当两特征的相关系数绝对值很小时,两特征值表示的向量接近在同一条直线上。当相关系值为负数时,表示负相关

<2>皮尔逊相关系数:pearsonr相关系数计算公式, 该公式出自于概率论

对于两组数据 𝑋={𝑥1,𝑥2,…,𝑥𝑛} 和 𝑌={𝑦1,𝑦2,…,𝑦𝑛},皮尔逊相关系数可以用以下公式计算:

ρ = Cos ⁡ ( x , y ) D x ⋅ D y = E [ ( x − E x ) ( y − E y ) ] D x ⋅ D y = ∑ i = 1 n ( x − x ~ ) ( y − y ˉ ) / ( n − 1 ) ∑ i = 1 n ( x − x ˉ ) 2 / ( n − 1 ) ⋅ ∑ i = 1 n ( y − y ˉ ) 2 / ( n − 1 ) \rho=\frac{\operatorname{Cos}(x, y)}{\sqrt{D x} \cdot \sqrt{D y}}=\frac{E[(x-E x)(y-E y)]}{\sqrt{D x} \cdot \sqrt{D y}}=\frac{\sum_{i=1}^{n}(x-\tilde{x})(y-\bar{y}) /(n-1)}{\sqrt{\sum_{i=1}^{n}(x-\bar{x})^{2} /(n-1)} \cdot \sqrt{\sum_{i=1}^{n}(y-\bar{y})^{2} /(n-1)}} ρ=Dx Dy Cos(x,y)=Dx Dy E[(xEx)(yEy)]=i=1n(xxˉ)2/(n1) i=1n(yyˉ)2/(n1) i=1n(xx~)(yyˉ)/(n1)

x ˉ \bar{x} xˉ y ˉ \bar{y} yˉ 分别是𝑋和𝑌的平均值

|ρ|<0.4为低度相关; 0.4<=|ρ|<0.7为显著相关; 0.7<=|ρ|<1为高度相关

<3>api:

scipy.stats.personr(x, y) 计算两特征之间的相关性

返回对象有两个属性:

statistic皮尔逊相关系数[-1,1]

pvalue零假设(了解),统计上评估两个变量之间的相关性,越小越相关

<4>示例:

from scipy.stats import pearsonr
def association_demo():
     # 1、获取数据
    data = pd.read_csv("src/factor_returns.csv")
    data = data.iloc[:, 1:-2]
     # 计算某两个变量之间的相关系数
    r1 = pearsonr(data["pe_ratio"], data["pb_ratio"])
    print(r1.statistic) #-0.0043893227799362555 相关性, 负数表示负相关
    print(r1.pvalue) #0.8327205496590723        正相关性
    r2 = pearsonr(data['revenue'], data['total_expense'])
    print(r2) #PearsonRResult(statistic=0.9958450413136111, pvalue=0.0)
    return None
association_demo()
    

开发中一般不使用求相关系数的方法,一般使用主成分分析,因为主成分分样过程中就包括了求相关系数了。

2.主成份分析(PCA)

成分分析(Principal Component Analysis, PCA)是一种广泛应用于数据降维和特征提取的统计方法。PCA 的目的是通过正交变换将一组可能存在相关性的变量转换成一组线性不相关的变量,这些新的变量被称为“主成分”。

PCA 的目标

降维:减少数据集的维度,同时保留数据的主要特征。
数据可视化:将高维数据转换为低维数据,便于可视化。
数据压缩:通过保留最重要的特征来压缩数据,减少存储空间和计算成本。
去噪:通过去除数据中的噪声成分来提高数据质量。

PCA 的原理

协方差矩阵:PCA 首先计算数据集的协方差矩阵,协方差矩阵反映了各变量之间的线性关系。
特征值与特征向量:求解协方差矩阵的特征值和对应的特征向量。特征值表示主成分的方向,特征向量表示主成分的大小。
排序:按照特征值的大小对特征向量进行排序,特征值越大,表示该方向上的方差越大。
选择主成分:选择前 k 个最大的特征值对应的特征向量作为主成分,k 通常是用户指定的目标维度。
数据投影:将原始数据投影到选定的主成分上,完成数据降维。

PCA 的步骤
数据预处理:

标准化数据,确保每个特征具有零均值和单位方差。

计算协方差矩阵:

计算数据集的协方差矩阵。

求解特征值和特征向量:

求解协方差矩阵的特征值和对应的特征向量。

选择主成分:

选择最大的 k 个特征值对应的特征向量作为主成分。

数据投影:

将原始数据投影到选定的主成分上,得到降维后的数据。

PCA 的优缺点
优点

简单直观:PCA 是一种简单且直观的降维方法。
去除冗余:PCA 能够去除数据中的冗余信息。
提高效率:通过减少数据维度,可以提高后续处理步骤的效率。

缺点

信息损失:虽然 PCA 试图保留最多的信息,但在降维过程中仍然会有信息损失。
非线性关系:PCA 不能处理数据中的非线性关系。
解释性:PCA 生成的新特征可能难以解释。

3.api

  • from sklearn.decomposition import PCA
  • PCA(n_components=None)
    • 主成分分析
    • n_components:
      • 实参为小数时:表示降维后保留百分之多少的信息
      • 实参为整数时:表示减少到多少特征
(3)示例-n_components为小数
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
import numpy as np

# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target

# 实例化 PCA
pca = PCA(n_components=2)  # 选择保留两个主成分

# 拟合并转换数据
X_pca = pca.fit_transform(X)

# 输出降维后的数据
print("原始数据的形状:", X.shape)
print("降维后的数据形状:", X_pca.shape)
print("降维后的数据:")
print(X_pca)

能够去除数据中的冗余信息。
提高效率:通过减少数据维度,可以提高后续处理步骤的效率。

缺点

信息损失:虽然 PCA 试图保留最多的信息,但在降维过程中仍然会有信息损失。
非线性关系:PCA 不能处理数据中的非线性关系。
解释性:PCA 生成的新特征可能难以解释。

3.api

  • from sklearn.decomposition import PCA
  • PCA(n_components=None)
    • 主成分分析
    • n_components:
      • 实参为小数时:表示降维后保留百分之多少的信息
      • 实参为整数时:表示减少到多少特征
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
import numpy as np

# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target

# 实例化 PCA
pca = PCA(n_components=2)  # 选择保留两个主成分

# 拟合并转换数据
X_pca = pca.fit_transform(X)

# 输出降维后的数据
print("原始数据的形状:", X.shape)
print("降维后的数据形状:", X_pca.shape)
print("降维后的数据:")
print(X_pca)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值