sklearn特征值选取与处理

【机器学习】sklearn特征值选取与处理-LMLPHP

Scikit-learn,通常称为sklearn,是一个流行的Python机器学习库,用于各种机器学习任务,包括分类、回归、聚类、降维、特征选择、模型选择和预处理数据等。它提供了许多工具和算法,使机器学习的实现变得相对容易。以下是一些scikit-learn的主要作用:

  • 机器学习算法:Scikit-learn包含了多种经典的监督学习算法,如支持向量机、决策树、随机森林、朴素贝叶斯、线性回归等,以及非监督学习算法,如K均值聚类和主成分分析等。这些算法可以用于各种任务,包括分类、回归和聚类。

  • 数据预处理:scikit-learn提供了数据预处理工具,用于数据清洗、缩放、特征选择、降维等操作,以准备数据供机器学习模型使用。这些工具有助于提高模型性能和准确性。

  • 模型评估:该库包括了用于评估机器学习模型性能的各种指标和技术,如交叉验证、网格搜索和学习曲线。这有助于选择最适合任务的模型和参数。

  • 特征工程:Scikit-learn提供了用于特征工程的工具,包括特征选择和特征提取方法,以改善模型性能并降低维度。

  • 数据可视化:该库还包含用于可视化数据和模型性能的工具,如绘图和图形化工具,以便更好地理解数据和模型的行为。

1. 调用数据集与数据集的划分

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# 调用数据集
def dataset_demo():
    iris = load_iris()  #加载Iris数据集
    print(f"查看数据集\n{iris}")
    print(f"查看数据集描述\n{iris['DESCR']}")
    print(f"查看特征值的名字\n{iris.feature_names}")
    print(f"查看特征值\n,iris.data,iris.data.shape")

    # 数据集的划分
    model_selection_demo(iris)
    return None

# 数据集划分
def model_selection_demo(iris):
    # sklearn.model_selection.train_test_split(arrays, *options)
    # x数据集的特征值,y数据集的标签值
    # test_size测试集的大小,一般为float
    # random_state随机数种子,不同的种子会造成不同的随机采样结果,相同的种子采样结果相同
    # return 训练集特征值 测试集特征值 训练集目标值 测试集目标值 x_train x_test y_train y_test
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size= 0.2)
    print(x_train, x_test, y_train, y_test)

2. 字典特征选取

from sklearn.feature_extraction import DictVectorizer

# 字典特征选取
def dict_demo():
    # sklearn.feature_extraction.DictVectorizer(sparse= True,...)
    # DictVectorizer.fit_transform(X)X:字典或者包含字典的迭代器返回值,返回sparse(稀疏)矩阵(将非零值按位置表示出来,提高加载效率)
    # DictVectorizer.inverse_transform(X)X:array数组或者sparse矩阵 返回值:转换之前数据格式
    # DictVectorizer.get_feature_names()返回类别名称
    # 字典特征提取,将类别转化为one-hot编码
    data = [{"city": "北京", "temperature": 100},
            {"city": "上海", "temperature": 70},
            {"city": "广州", "temperature": 40}]
    # 实例化一个转换器类
    transfer = DictVectorizer(sparse= False)  # sparse矩阵等价于二维数组
    # 调用fit_transform()
    data_new = transfer.fit_transform(data)
    print(f"data_new{data_new}")
    print(f"特征名字\n{transfer.get_feature_names_out()}")
    return None
注:这是transfer = DictVectorizer(sparse= True)
data_new[[  0.   1.   0. 100.]
 [  1.   0.   0.  70.]
 [  0.   0.   1.  40.]]
特征名字
['city=上海' 'city=北京' 'city=广州' 'temperature']
注:这是transfer = DictVectorizer(sparse= False)
data_new  (0, 1)	1.0
  (0, 3)	100.0
  (1, 0)	1.0
  (1, 3)	70.0
  (2, 2)	1.0
  (2, 3)	40.0
特征名字
['city=上海' 'city=北京' 'city=广州' 'temperature']

3. 英文文本特征值选取

from sklearn.feature_extraction.text import CountVectorizer

# 文本特征值选取
def text_demo():
    # sklearn.feature_extraction.text.CountVectorizer(stop_word[])stop_word[]:停用的,一些词不适合作为特征值(停用词表)
    # CountVectorizer.fit_transform(X)X:文本或者包含文本字符串的可迭代对象 返回值:返回sparse矩阵
    # CountVectorizer。inverse_transform(X)X:array数组或者sparse矩阵 返回值:转换之前数据格
    # sklearn.feature_extraction.text.TfidVectorizer
    text = ["life is short, i like like python", "life is too long, i dislike python"]
    # 实例化一个转化器类
    transfer = CountVectorizer()
    text_new = transfer.fit_transform(text)
    print(f"text_new:\n{text_new.toarray()}")  # 简单来说就是统计特征词个数
    print(f"text_feature:\n{transfer.get_feature_names_out()}")
text_new:
[[0 1 1 2 0 1 1 0]
 [1 1 1 0 1 1 0 1]]
text_feature:
['dislike' 'is' 'life' 'like' 'long' 'python' 'short' 'too']

4. 中文特征值选取

from sklearn.feature_extraction.text import CountVectorizer

# 中文文本特征抽取
def text_chinese_demo():
    # 默认情况下只会抽取两个词及以上的 而且默认以空格分隔
    text_1 = ["我 是一 个 大帅逼!", "我 是一 个 聪明逼!"]
    text_2 = ["我是一个大帅逼!", "我是一个聪明逼!"]
    transfer_1 = CountVectorizer()
    transfer_2 = CountVectorizer()
    text_new_1 = transfer_1.fit_transform(text_1)
    text_new_2 = transfer_2.fit_transform(text_2)
    print(f"text_new_1:\n{text_new_1.toarray()}")
    print(f"text_name_1:\n{transfer_1.get_feature_names_out()}")
    print(f"text_new_2:\n{text_new_2.toarray()}")
    print(f"text_name_2:\n{transfer_2.get_feature_names_out()}")
text_new_1:
[[1 1 0]
 [0 1 1]]
text_name_1:
['大帅逼' '是一' '聪明逼']
text_new_2:
[[1 0]
 [0 1]]
text_name_2:
['我是一个大帅逼' '我是一个聪明逼']

5. 中文分词文本特征抽取

import jieba
from sklearn.feature_extraction.text import CountVectorizer

# 中文分词文本特征抽取
def text_chinese_jieba_demo():
    text = ["今天很残酷,明天更残酷,后天很美好,",
            "但绝对大部分是死在明天晚上,所以每个人不要放弃今天。",
            "我们看到的从很远星系来的光是几百万年之前发出的,",
            "这样当我们看到宇宙时,我们是在看他的过去。",
            "如果只用一种方法了解某样事物,你就不会真正了解它。",
            "了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。"]
    text_change = []
    for sent in text:
        text_change.append(cut_text(sent))
    transfer = CountVectorizer()
    text_final = transfer.fit_transform(text_change)
    print(f"text_final:\n{text_final.toarray()}")
    print(f"text_name:\n{transfer.get_feature_names_out()}")
    
# jieba的文本分词
def cut_text(text):
    """
    进行中文分词:"我爱北京天安门"--》"我 爱 北京 天安门"
    :return: 
    """
    return " ".join(list(jieba.cut(text)))  # join整合成字符串
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\85710\AppData\Local\Temp\jieba.cache
text_final:
[[0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 1 0 0 0]
 [0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 1 0 1 0 0 1 0 0 0 1 0 0 0 0]
 [0 0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1]
 [1 1 0 0 2 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0]
 [0 0 0 0 2 2 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0]]
text_name:
['一种' '不会' '不要' '之前' '了解' '事物' '今天' '光是' '几百万年' '发出' '取决于' '只用' '后天' '含义'
 '大部分' '如何' '如果' '宇宙' '我们' '所以' '放弃' '方法' '明天' '星系' '晚上' '某样' '残酷' '每个'
 '看到' '真正' '秘密' '绝对' '美好' '联系' '过去' '这样']
Loading model cost 0.330 seconds.
Prefix dict has been built successfully.

6. TfidfVectorizer特征抽取

​ 考虑词语重要性:TfidfVectorizer 考虑每个词语在文本集合中的重要性,而不仅仅是它们的出现频率。它通过计算每个词语的TF-IDF分数,反映了一个词语在一个文档中的频率与在整个文本集合中的重要性之间的平衡。这有助于减少常见但无关紧要的词语的权重,增加关键词的权重。这意味着像“the”、“a”、“an”等常见的停用词会有较低的权重。

import jieba
from sklearn.feature_extraction.text import TfidfVectorizer

# TfidfVectorizer的特征抽取
def text_tfidf_chinese_demo():
    """
    TF-IDF的主要思想是:如果某一个词或者短语再一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。作用:用于评估一字词对于一个文件集或者一个语料库中的其中一份文件的重要程度

    公式:
        词频(term frequency,tf)指的是某一个给定的词语在该文件中出现的频率
        逆向文档频率(inverse document frequency,idf)是一个词语普遍重要性的度量,某一特定词语的idf,可以由总文件
        数目除以包含该词语之文件的数目,再将得到的商取以10为底的对数得到
        tfidf(i,j)=tf(i,j)*idf(i)
        例如:1000篇文章,100篇文章包含“经济”,而文章A(100词)10次经济则:
            tf:10/100=0.1
            idf:lg 1000/10=2
            tfidf=0.1*2=0.2

    sklearn.feature_extraction.text.TfidfVectorizer(stop_words=None,...)
    返回词的权重矩阵
        TfidfVectorizer.fit_transform(X)X:文本或者包含文本字符串的可迭代对象
        返回值:返回sparse矩阵
        TfidfVectorizer.inverse_transform(X)X:array数组或者sparse矩阵
        返回值:转换之前数据格式
        TfidfVectorizer。get_feature_names()
        返回值:单词列表
    :return:
    """
    text = ["今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。",
        "我们看到的从很远星系来的光是几百万年之前发出的,这样当我们看到宇宙时,我们是在看他的过去。",
        "如果只用一种方法了解某样事物,你就不会真正了解它,了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。"]
    text_change = []
    for sent in text:
        text_change.append(cut_text(sent))
    # 实例化一个转换器类
    transfer = TfidfVectorizer(stop_words= ["一种", "所以"])
    # 调用fit_transform
    text_final = transfer.fit_transform(text_change)
    print(f"text_final:\n{text_final.toarray()}")
    print(f"text_name:\n{transfer.get_feature_names_out()}")
    
# jieba的文本分词
def cut_text(text):
    """
    进行中文分词:"我爱北京天安门"--》"我 爱 北京 天安门"
    :return: 
    """
    return " ".join(list(jieba.cut(text)))  # join整合成字符串
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\85710\AppData\Local\Temp\jieba.cache
Loading model cost 0.315 seconds.
Prefix dict has been built successfully.
text_final:
[[0.         0.2236068  0.         0.         0.         0.4472136
  0.         0.         0.         0.         0.         0.2236068
  0.         0.2236068  0.         0.         0.         0.
  0.2236068  0.         0.4472136  0.         0.2236068  0.
  0.4472136  0.2236068  0.         0.         0.         0.2236068
  0.2236068  0.         0.         0.        ]
 [0.         0.         0.2410822  0.         0.         0.
  0.2410822  0.2410822  0.2410822  0.         0.         0.
  0.         0.         0.         0.         0.2410822  0.55004769
  0.         0.         0.         0.2410822  0.         0.
  0.         0.         0.48216441 0.         0.         0.
  0.         0.         0.2410822  0.2410822 ]
 [0.15895379 0.         0.         0.63581516 0.47686137 0.
  0.         0.         0.         0.15895379 0.15895379 0.
  0.15895379 0.         0.15895379 0.15895379 0.         0.12088845
  0.         0.15895379 0.         0.         0.         0.15895379
  0.         0.         0.         0.31790758 0.15895379 0.
  0.         0.15895379 0.         0.        ]]
text_name:
['不会' '不要' '之前' '了解' '事物' '今天' '光是' '几百万年' '发出' '取决于' '只用' '后天' '含义' '大部分'
 '如何' '如果' '宇宙' '我们' '放弃' '方法' '明天' '星系' '晚上' '某样' '残酷' '每个' '看到' '真正'
 '秘密' '绝对' '美好' '联系' '过去' '这样']

7. 归一化处理

想象一下你有一些不同单位和范围的数据,比如身高(以英寸为单位)和体重(以磅为单位),以及温度(以摄氏度为单位)和湿度(以百分比表示)。如果你要比较或分析这些数据,你会发现它们的值在数量级上差异很大。归一化的作用就像将所有这些数据都转化为相同的标度或单位,例如将所有数据都映射到0到1的范围内。这使得数据更容易进行比较和分析,因为它们现在具有相似的尺度。总之,归一化的目的是让不同特征的数据在相似的尺度上操作。(输出略)

import pandas as pd
from sklearn.preprocessing import MinMaxScaler

# 归一化处理
def minmax_demo():
    """
    归一化处理
    sklearn.preprocessing.MinMaxScalar(feature_range=(0,1),...)
    MinMaxScalar.fit_transform(X)X:numpy array格式的数据(N_sample,n_feature)
    返回值:转换后的形状相同的array
    :return:
    """
    data = pd.read_csv("dating.txt")
    data = data.iloc[:, :3]
    print(f"data:\n{data}")
    # 实例化一个转换器类
    transfer = MinMaxScaler(feature_range= (0,1))
    data_new = transfer.fit_transform(data)
    print(f"data_new:\n{data_new}")

8. 标准化处理

标准化是一种数据处理技巧,其主要目的是将数据转化为均值为0、标准差为1的标准分布,以便更好地进行比较和分析。其中,归一化处理和标准化处理的区别:

  1. 归一化:

    • 目标:将数据映射到一个相似的尺度,通常在0到1之间。
    • 方法:通过调整数据的范围,使其在相似的尺度内进行比较。
    • 适用性:通常用于处理数据特征的范围不一致,但不关心数据的均值和标准差。
    • 示例:将不同特征的值都缩放到0到1范围内,以便比较它们的重要性。
  2. 标准化:

    • 目标:将数据转化为均值为0、标准差为1的标准正态分布。
    • 方法:通过减去均值并除以标准差,将数据调整到均值为0、标准差为1的标准分布。
    • 适用性:通常用于需要均值和标准差相似的数据,以便某些统计和机器学习算法更好地运行。
    • 示例:确保不同特征的数据都符合标准正态分布,以满足某些模型的假设。

简而言之,归一化关注数据范围的调整,使其在0到1之间,而标准化关注将数据调整到均值为0、标准差为1的标准正态分布。选择使用哪种处理取决于数据和任务的性质,以及特定算法的要求。

import pandas as pd
from sklearn.preprocessing import StandardScaler

# 标准化处理
def standard_demo():
    """
    sklearn.preprocessing.Standardscaler()
    处理之后,对每一列来说所有数据都聚集在均值0附近,标准差为1
    StandardScaler.fit_transform(X)X:numpy array格式的数据[n_samples,n_features]
    返回值:转换之后形状相同的array
    :return:
    """
    data = pd.read_csv("dating.txt")
    data = data.iloc[:, :3]
    # 实例化一个转换器对象
    transfer = StandardScaler()
    data_new = transfer.fit_transform(data)
    print(f"data_new:\n{data_new}")
    print(f"data_new:\n{transfer.get_feature_names_out()}")

9. 过滤低方差特征

当处理数据时,我们通常面临着众多特征(也叫属性或变量),这些特征可以是数据集中的列,例如身高、体重、年龄等。特征选择和相关系数计算是用来理解和处理这些特征的重要工具。特征选择是一种技术,用于从所有可用的特征中挑选出最重要或最相关的特征,以便在建立机器学习模型或进行数据分析时,仅使用那些对问题最有帮助的特征。这有助于简化模型、减少计算成本,提高模型性能,以及更好地理解数据。在特征选择过程中,我们通常考虑特征的重要性、相关性、方差等因素来决定是否保留或丢弃某个特征。相关系数是用来衡量两个特征之间关系强度和方向的统计指标。在数据分析中,我们常常想知道某两个特征是否与彼此相关,以及它们之间的关系是正相关还是负相关。最常见的相关系数是皮尔逊相关系数(Pearson correlation coefficient),它的值介于-1和1之间。如果相关系数接近1,表示两个特征正相关(当一个增加时,另一个也增加),如果接近-1,表示它们负相关(一个增加时,另一个减少),如果接近0,表示它们没有线性相关性。

from sklearn.feature_selection import VarianceThreshold
import pandas as pd

# 过滤低方差特征, 相关系数(特征与特征之间的相关性)
def variance_demo():
    """
    特征与特征之间相关性很高的话,可以选取其中一个、加权求和或主成分分析
    :return:
    """

    data = pd.read_csv("factor_returns.csv")
    data = data.iloc[:, 1:-2]
    # 实例化一个转化器类
    transfer = VarianceThreshold(threshold= 10)
    data_new = transfer.fit_transform(data)
    print(data_new, '\n', data_new.shape)
    # 相关系数
    r = pearsonr(data["pe_ratio"], data["pb_ratio"])
    print(f"相关系数:{r}")

10. 主成分分析

主成分分析(Principal Component Analysis,简称PCA)是一种用于降维和数据压缩的数学技术。它的主要目标是简化数据集,同时尽量保留数据中的重要信息。想象一下你有一大堆数据,每个数据点都有很多特征。PCA的任务就是帮助你找到数据中的一些“主要成分”或“主要特征”,这些主成分是数据中变化最大的方向。它通过将数据在新的坐标系中表示,其中坐标轴被称为主成分,以便在新坐标系中,数据的方差尽量大,这意味着它们包含了原始数据中的大部分信息。通俗来说,PCA就像你在观察星星的夜空时,尝试找到一个新坐标系,其中坐标轴是定位最多星星的方向,从而使你可以用更少的坐标轴来描述整个星空。这不仅有助于减小数据的维度,还可以消除数据中的冗余信息,帮助更好地可视化和理解数据。PCA在数据分析、图像处理、模式识别和降维领域非常有用,它可以用来简化复杂数据集,减少噪音,加速机器学习算法的训练,以及提供对数据的更清晰的洞察。

from sklearn.decomposition import PCA、

# 主成分分析
def pca_demo():
    """
    主成分分析(PCA)
    定义:高维数据转化为低维数据的过程,在此过程中可能会舍弃原有数据,创建新的变量
    作用:数据维度压缩,尽可能降低原数据的维度(复杂度),损失最少量信息
    应用:回归分析或者聚类分析中
    sklearn.decomposition.PCA(n_components=None)
    将数据分解为较低维数空间
    n_components:
        小数:表示保留百分之多少的信息
        整数:减少到多少特征
    PCA.fit_transform(X)X:numpy array格式的数据[n_samples,n_features]
    返回值:转化后指定维度的array
    :return:
    """
    data = [
        [2,8,4,5],
        [6,3,0,8],
        [5,4,9,1]
    ]
    # 实例化一个对象
    transfer_1 = PCA(n_components= 2)
    data_new_1 = transfer_1.fit_transform(data)
    print(f"data_new_1:\n{data_new_1}\n")
    transfer_2 = PCA(n_components= 0.95)
    data_new_2 = transfer_2.fit_transform(data)
    print(f"data_new_2:\n{data_new_2}\n")
    # 对比得到:即降了一半,也保留了大部分的信息

11. 案例:探究用户对物品类别的喜好细分降维

  • order_products_prior.csv:订单与商品信息
    • 字段:order_id,product_id,add_to_cart_order,reordered
  • products.csv:商品信息
    • 字段:product_id,product_name,aisle_id,department_id
  • orders.csv:用户的订单信息
    • 字段:order_id,user_id,eval_set,order_number,…
  • aisles.csv:商品所属具体物品类别
    • 字段:aisle_id,aisle

  • 目标:探究用户和商品之间的关系
  • 实现:获取数据;将user_id和aisle放在同一个表中合并;找到user_id和aisle关系(交叉表和透视表);特征冗余过多(PCA)降维。

Pandas教程 | Merge数据合并图文详解

# 示例
def demo_1():
    # 获取数据
    order_products = pd.read_csv("./1/order_products__prior.csv")
    products = pd.read_csv("./1/products.csv")
    orders = pd.read_csv("./1/orders.csv")
    aisles = pd.read_csv("./1/aisles.csv")

    # 数据合并
    table_1 = pd.merge(aisles, products, on= ["aisle_id", "aisle_id"])
    table_2 = pd.merge(table_1, order_products, on= ["product_id", "product_id"])
    table_3 = pd.merge(table_2, orders, on= ["order_id", "order_id"])

    # 找到user_id和aisle之间的关系
    table = pd.crosstab(table_3["user_id"], table_3["aisle"])
    table.to_csv("table_.csv",index=False)
    
    # PCA降维
    transfer = PCA(n_components= 0.95)
    data_new = transfer.fit_transform(table)
    print(f"data_new:{data_new}")
    print(f"data_new_shape:{data_new.shape}")
10-25 15:45