11.12 机器学习-特征工程
# 特征工程:就是对特征进行相关的处理
# 一般使用pandas来进行数据清洗和数据处理、使用sklearn来进行特征工程
# 特征工程是将任意数据(如文本或图像)转换为可用于机器学习的数字特征,比如:字典特征提取(特征离散化)、文本特征提取、图像特征提取。
# 特征工程步骤为:
# - 特征提取, 如果不是像dataframe那样的数据,要进行特征提取,比如字典特征提取,文本特征提取
# - 无量纲化(预处理)
# - 归一化
# - 标准化
# - 降维
# - 底方差过滤特征选择
# - 主成分分析-PCA降维
# 稀疏矩阵 0元素占比很多的矩阵
# 可以用三元组来表示稀疏矩阵
# ()里面表示矩阵的一个元素的坐标 后面的数值为这个坐标元素的值 其他没有表示出来的元素全为0
# (0,0) 10
# (0,1) 20
# (2,0) 90
# (2,20) 8
# (8,0) 70
# DictVectorizer 字典列表特征提取 # 字典转化为向量(矩阵np数组)
from sklearn.feature_extraction import DictVectorizer
from sklearn.feature_extraction.text import CountVectorizer,TfidfVectorizer
from sklearn.preprocessing import MinMaxScaler,StandardScaler
from sklearn.feature_selection import VarianceThreshold
from sklearn.decomposition import PCA
import pandas as pd
import numpy as np
import jieba
def dict_vectorizer():
# 初始化工具类 得到一个工具
mode1=DictVectorizer(sparse=False) # sparse 是否返回稀疏矩阵 默认三元组返回形式
data=data = [{'city':'成都', 'age':30, 'temperature':200}, {'city':'重庆','age':33, 'temperature':60}, {'city':'北京', 'age':42, 'temperature':80}]
# 使用工具进行字典列表特征提取 mode1.fit_transform
data2=mode1.fit_transform(data)
data2.dtype="i2"
print(data2)
# 转化之后 mode1有get_feature_names_out()方法 获取全部的特征名称
# print(mode1.get_feature_names_out())
# 转为DF
df1=pd.DataFrame(columns=mode1.get_feature_names_out())
df1[mode1.get_feature_names_out()]=data2
print(df1)
# CountVectorizer 文本特征提取
# sklearn.feature_extraction.text.CountVectorizer
# 构造函数关键字参数stop_words,值为list,表示词的黑名单(不提取的词)
# fit_transform函数的返回值为稀疏矩阵 使用 toarray() 方法将其转换为一个普通的 NumPy 二维数组 np数组里面的每一个的嵌套数组为一个文档的词频
# 提取出来的是词频 就是数据中 一个词语出现的频次 会剔除一些无意义的词语 以空格分词 a an 以及一些单个的词
def count_vectorizer():
data=["stu is well, stu is great", "You like stu"]
# 初始化工具
mode1=CountVectorizer(stop_words=["well"]) # stop_words 传入的是list
data2=mode1.fit_transform(data) # data 是一个字符串列表 每一个元素为一个文档
# 稀疏矩阵转为np数组 #稀疏矩阵不好转df
data3=data2.toarray()
# 转为df
df1=pd.DataFrame(columns=mode1.get_feature_names_out())
df1[mode1.get_feature_names_out()]=data3
print(df1)
# 专门定义一个jieba方法对中文进行分词
def jba(text):
text2=list(jieba.cut(text))
text3=" ".join(text2)
return text3
# 中文文本提取 使用jieba分词器
# jieba.cut()传入字符串自动分词短词 分词返回一个对象 把这个对象用list()变为列表 用str.jion 空格隔开
def chinese_vectorizer():
arr=list(jieba.cut("我爱北京天安门"))
# 把列表转为str 并且每一个元素之间用 空格隔开 然后使用CountVectorizer提取
str1=" ".join(arr)
print(str1)
mode1=CountVectorizer(stop_words=[])
data=[str1]
data2=mode1.fit_transform(data)
print(data2.toarray())
print(mode1.get_feature_names_out())
def chinese_vectorizer2():
data = ["教育学会会长期间,坚定支持民办教育事业!", "扶持民办,学校发展事业","事业做出重大贡献!"]
data2=[jba(i) for i in data]
mode1=CountVectorizer(stop_words=[])
data3=mode1.fit_transform(data2)
data4=data3.toarray()
df1=pd.DataFrame(columns=mode1.get_feature_names_out())
df1[mode1.get_feature_names_out()]=data4
print(df1)
pass
# TfidfVectorizer TF-IDF文本特征词的重要程度特征提取 词频* 逆文档频率
# 值越大:意味着该词语在当前文档中的词频较高(TF大),并且在整个文件集中出现的文档频率较低(IDF大),因此这个词语在当前文档中相对较为重要且稀有。
# 值越小:则相反,可能意味着该词语在当前文档中的词频较低,或者在整个文件集中出现的文档频率较高,因此这个词语在当前文档中相对不那么重要且不稀有。
# 词频(Term Frequency, TF), 表示一个词在当前篇文章中的重要性 列表中的一个文档中 某个词语出现的次数/文档的词语总数
# 逆文档频率(Inverse Document Frequency, IDF), 反映了词在整个文档集合中的稀有程度 lg(文档总数+1/本词出现的文档数+1)
# 如果一个词在很多文档中都出现,那么它的IDF值就会较低;反之,如果一个词只在少数文档中出现,那么它的IDF值就会较高。IDF的计算公式为总文档数除以包含该词的文档数的对数。
def TF_IDF():# 文本特征词的重要程度特征提取
# sklearn.feature_extraction.text.TfidfVectorizer() 创建得到工具TF-IDF值的工具
# 构造函数关键字参数stop_words,表示词特征黑名单
# fit_transform函数的返回值为稀疏矩阵
data = ["教育学会会长期间,坚定支持民办教育事业!", "扶持民办,学校发展事业","事业做出重大贡献!"]
data2=[jba(i) for i in data]
# 创建工具
transform1=TfidfVectorizer(stop_words=[])
data3=transform1.fit_transform(data2)
data4=data3.toarray()
df1=pd.DataFrame(columns=transform1.get_feature_names_out())
df1[transform1.get_feature_names_out()]=data4
print(df1)
pass
# 无量纲化 分为归一化和标准化
# 无量纲,即没有单位的数据
# 无量纲化包括"归一化"和"标准化", 为什么要进行无量纲化呢?
# | 1 | 1.75(米) | 15000(元) | 120(斤) |
# | 2 | 1.5(米) | 16000(元) | 140(斤) |
# | 3 | 1.6(米) | 20000(元) | 100(斤) |
# 假设算法中需要求它们之间的欧式距离, 这里以编号1和编号2为示例:
# $L = \sqrt{(1.75-1.5)^2+(15000-16000)^2+(120-140)^2}$
# 从计算上来看, 发现身高对计算结果没有什么影响, 基本主要由收入来决定了,但是现实生活中,身高是比较重要的判断标准. 所以需要无量纲化.
# MinMaxScaler 归一化 结果的默认范围为0-1 如果像归一到其他范围要变换 最小值最大值归一化
# 公式 归一化后的X值为 (X-本项X的最小值)/(本项X的最大值-本项X的最小值)
# API:
# sklearn.preprocessing.MinMaxScaler(feature_range)
# 参数:feature_range=(0,1) 归一化后的值域,可以自己设定
# fit_transform函数归一化的原始数据类型可以是list、DataFrame和ndarray, 不可以是稀疏矩阵
# fit_transform函数的返回值为ndarray
# 缺点
# 最大值和最小值容易受到异常点影响,比如马云的收入太大了肯定是最大值(其他人的收入太小了,那归一化的结果受到马云的影响太大了)所以鲁棒性(健壮性)较差。所以常使用标准化的无量钢化
def min_max_scaler():
df1=pd.read_csv("assets/people1.csv")
scaler1=MinMaxScaler()
df2=scaler1.fit_transform(df1)
print(df2)
print(type(df2))
pass
# StandardScaler 标准化 结果肯定缩小了但不是一个固定的范围了 这个算法以大多数人优先 不会受到一个特别大的值影响
# 在机器学习中,标准化是一种数据预处理技术,也称为数据归一化或特征缩放。它的目的是将不同特征的数值范围缩放到统一的标准范围,以便更好地适应一些机器学习算法,特别是那些对输入数据的尺度敏感的算法。
# 标准化公式
# 最常见的标准化方法是Z-score标准化,也称为零均值标准化。它通过对每个特征的值减去其均值,再除以其标准差,将数据转换为均值为0,标准差为1的分布。这可以通过以下公式计算:
# (X-X的均值)/X的标准差 标准差为方差的开根号
# API:
# sklearn.preprocessing.StandardScale
# 与MinMaxScaler一样,原始数据类型可以是list、DataFrame和ndarray
# fit_transform函数的返回值为ndarray, 归一化后得到的数据类型都是ndarray
def standard_scale():
scale1=StandardScaler()
np.random.seed(666)
data=np.random.randint(0,100,(20,5))
data2=scale1.fit_transform(data)
print(data2)
print("-----------")
pass
# fit_transform解析
def fit_transform1():
# fit_transform 是fit 和transform 的合体
# fit的作用是计算 transform是变换 fit一个数据集后 变化器就存入了 这个数据集的方差之类的数据 可以用来给其他的单条数据进行运算 标准化
scale1=StandardScaler()
np.random.seed(666)
data=np.random.randint(0,100,(20,5))
data2=scale1.fit(data)
data3=scale1.transform(data)
print(data3)
pass
# 特征降维 比如一个很大的有很多特征的数据集 某个特征的变化特别小全为1 那它对结果就没有影响 通过方差看 某一个特征自己变但结果不跟着变
# 实际数据中,有时候特征很多,会增加计算量,降维就是去掉一些特征,或者转化多个特征为少量个特征
# **特征降维其目的**:是减少数据集的维度,同时尽可能保留数据的重要信息。
# **特征降维的好处**:
# 减少计算成本:在高维空间中处理数据可能非常耗时且计算密集。降维可以简化模型,降低训练时间和资源需求。
# 去除噪声:高维数据可能包含许多无关或冗余特征,这些特征可能引入噪声并导致过拟合。降维可以帮助去除这些不必要的特征。
# **特征降维的方式:**
# - 特征选择
# - 从原始特征集中挑选出最相关的特征 去掉不相关的特征
# - 主成份分析(PCA)
# - 主成分分析就是把之前的特征通过一系列数学计算,形成新的特征,新的特征数量会小于之前特征数量 合成特征
# 特征选择的一种方式
# VarianceThreshold 低方差过滤特征选择 过滤掉方差低的特征
# 1. **计算方差**:对于每个特征,计算其在训练集中的方差(每个样本值与均值之差的平方,在求平均)。
# 2. **设定阈值**:选择一个方差阈值,任何低于这个阈值的特征都将被视为低方差特征。
# 3. **过滤特征**:移除所有方差低于设定阈值的特征
# sklearn.feature_selection.VarianceThreshold(threshold=2.0)
def variance_threshold():
threshold1=VarianceThreshold(threshold=2.0)
x=[[0,2,0,3],
[0,1,4,9],
[0,1,1,3],
[0,4,2,8]
]
data=threshold1.fit_transform(x)
print(data)
# 特征选择的另一种方式 主成份分析(PCA) 已经包含此步骤
# 皮尔逊相关系数 |ρ|<0.4为低度相关; 0.4<=|ρ|<0.7为显著相关; 0.7<=|ρ|<1为高度相关
# PAC 主成份分析
# PCA的核心目标是从原始特征空间中找到一个新的坐标系统,使得数据在新坐标轴上的投影能够最大程度地保留数据的方差,同时减少数据的维度。
# API
# PCA(n_components=None)
# - 主成分分析
# - n_components:
# - 实参为小数时:表示降维后保留百分之多少的信息
# - 实参为整数时:表示减少到多少特征
def pac():
pac1=PCA(n_components=0.8)
data = [[2,8,4,5],
[6,3,0,8],
[5,4,9,1]]
data2=pac1.fit_transform(data)
print(data2)
if __name__=="__main__":
# dict_vectorizer()
# count_vectorizer()
# chinese_vectorizer()
# chinese_vectorizer2()
# TF_IDF()
# min_max_scaler()
# standard_scale()
# fit_transform1()
# variance_threshold()
pac()
pass