数据预处理

前提
数据预处理 针对 结构化数据(数据库存储模式)和非结构化数据(文字、视频、图像等)有各种不同独特方式处理。如图像的旋转、裁剪等,文字的提取分词、向量化等。
这里仅讨论 结构化数据通用预处理 ,部分也可适用于非结构化数据,具体使用根据实际情况而定。

—— 数据预处理(Python版) ——

0. 导入需要的库

import numpy as np
import pandas as pd 
import matplotlib.pyplot as plt

1. 加载数据

1.1 根据文件类型(常用 csv、txt、xlsx), 使用对应读取方式

data_csv = pd.read_csv(r'../../data/practice/insurance.csv')  #读取csv文件
data = pd.read_table(r'../../data/practice/TestFile.txt')  #读取txt文件
data = pd.read_excel(r'../../data/practice/excelTest.xlsx')  #读取excel文件
house_data = pd.read_csv(r'../../data/practice/housing.csv')

1.2 直接读取数据库

# 导入数据库模块
import pymysql
#创建游标
cur = conn.cursor()
#连接数据库,注意修改成要连的数据库信息
conn = pymysql.connect(host='localhost',user='root',passwd='12345',db='mydb')  
#train_data是要读取的数据名
cur.execute("select * from train_data limit 100")
#获取数据
data = cur.fetchall()
#获取列名
cols = cur.description
#执行
conn.commit()  
#关闭游标
cur.close()  
#关闭数据库连接
conn.close()
col = []
for i in cols:
    col.append(i[0])
data = list(map(list,data))
data = pd.DataFrame(data,columns=col)

1.3 CSV文件合并

当数据可能分布在一个个csv或者txt文档中时,可以将一个个文档合并到一个文件

#合并多个csv文件成一个文件
import glob

#合并
def file_merge():
    csv_list = glob.glob('*.csv') #查看同文件夹下的csv文件数
    print(u'共发现%s个CSV文件'% len(csv_list))
    print(u'正在处理............')
    for i in csv_list: #循环读取同文件夹下的csv文件
        fr = open(i,'rb').read()
        with open('result.csv','ab') as f: #将结果保存为result.csv
            f.write(fr)
    print(u'合并完毕!')

#去重    
def deduplicate(file):
    df = pd.read_csv(file,header=0)    
    datalist = df.drop_duplicates()    
    datalist.to_csv(file)

if __name__ == '__main__':    
    file_merge()
    deduplicate("result.csv.csv")

1.4 CSV文件拆分

数据量比较大的文件,直接读取或者打开比较困难,可以拆分数据,查看数据样式以及读取部分数据

##csv比较大,打不开,将其切分成一个个小文件,看数据形式
f = open('NEW_Data.csv','r') #打开大文件
i = 0 #设置计数器

#这里1234567表示文件行数,如果不知道行数可用每行长度等其他条件来判断
while i<1234567 : 
    with open('newfile'+str(i),'w') as f1:
        for j in range(0,10000) : #这里设置每个子文件的大小
            if i < 1234567: #这里判断是否已结束,否则最后可能报错
                f1.writelines(f.readline())
                i = i+1
            else:
                break

1.5 数据查看

显示前五行数据

data_csv.head()
agesexbmichildrensmokerregioncharges
019female27.9000.0yessouthwest16884.92400
118male33.7701.0nosoutheast1725.55230
228male33.0003.0nosoutheast4449.46200
333male22.7050.0nonorthwest21984.47061
432male28.8800.0nonorthwest3866.85520

显示末尾五行数据

data_csv.tail() 
agesexbmichildrensmokerregioncharges
133350male30.973.0nonorthwest10600.5483
133418female31.920.0nonortheast2205.9808
133518female36.850.0nosoutheast1629.8335
133621female25.800.0nosouthwest2007.9450
133761female29.070.0yesnorthwest29141.3603

查看各字段的信息

data_csv.info() 
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1338 entries, 0 to 1337
Data columns (total 7 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   age       1338 non-null   int64  
 1   sex       1338 non-null   object 
 2   bmi       1336 non-null   float64
 3   children  1337 non-null   float64
 4   smoker    1338 non-null   object 
 5   region    1338 non-null   object 
 6   charges   1337 non-null   float64
dtypes: float64(3), int64(1), object(3)
memory usage: 73.3+ KB

查看数据集有几行几列,data.shape[0]是行数,data.shape[1]是列数

data_csv.shape 
(1338, 7)

查看数据的大体情况,均值,最值,分位数值…

data_csv.describe() 
agebmichildrencharges
count1338.0000001336.0000001337.0000001337.000000
mean39.20702530.6673621.09573713274.901634
std14.0499606.1018801.20557112113.433665
min18.00000015.9600000.0000001121.873900
25%27.00000026.2725000.0000004738.268200
50%39.00000030.4000001.0000009386.161300
75%51.00000034.7000002.00000016657.717450
max64.00000053.1300005.00000063770.428010

得到列名的list

data_csv.columns.tolist()  
['age', 'sex', 'bmi', 'children', 'smoker', 'region', 'charges']

寻找相关性

相关系数的范围从-1变化到1。
越接近1,表示有越强的正相关,例如,收入中位数。
越接近-1,表示有较强的负相关,例如,经纬度。
越接近0,表示说明二者之间没有线性相关性。

# 计算每对属性之间的 皮尔逊 相关系数
corr_matrix = house_data.corr()
# 查看 房价与各个数值属性的 相关性  (下降)
corr_matrix['median_house_value'].sort_values(ascending=False)
median_house_value    1.000000
median_income         0.688075
total_rooms           0.134153
housing_median_age    0.105623
households            0.065843
total_bedrooms        0.049686
population           -0.024650
longitude            -0.045967
latitude             -0.144160
Name: median_house_value, dtype: float64

1.6 去除冗余

# 冗余处理
def re_check(df):
    flag = []
    for f in df.duplicated().values:
        flag.append(~f)
    df = df[flag]
    return df

if __name__=='__main__':
    df = pd.DataFrame({'a':['dog']*3+['fish']*3+['dog'],'b':[10,11,12,12,14,14,10]})
    display(df)
    df = re_check(df)
    display(df)
ab
0dog10
1dog11
2dog12
3fish12
4fish14
5fish14
6dog10
ab
0dog10
1dog11
2dog12
3fish12
4fish14

2. 缺失值

现实获取的数据经常存在缺失和不完整的情况,一般会对这些缺失数据进行识别和处理

2.1 缺失值查看

 #统计每列有几个缺失值
data_csv.isnull().sum()
age         0
sex         0
bmi         2
children    1
smoker      0
region      0
charges     1
dtype: int64
#找出存在缺失值的列
missing_col = data_csv.columns[data_csv.isnull().any()].tolist() 
missing_col
['bmi', 'children', 'charges']
#统计每个变量的缺失值占比
def CountNA(data):
    cols = data.columns.tolist()    #cols为data的所有列名
    n_df = data.shape[0]    #n_df为数据的行数
    for col in cols:
        missing = np.count_nonzero(data[col].isnull().values)  #col列中存在的缺失值个数
        mis_perc = float(missing) / n_df * 100
        print("{col}的缺失比例是{miss}%".format(col=col,miss=mis_perc))

CountNA(data_csv)
age的缺失比例是0.0%
sex的缺失比例是0.0%
bmi的缺失比例是0.14947683109118087%
children的缺失比例是0.07473841554559044%
smoker的缺失比例是0.0%
region的缺失比例是0.0%
charges的缺失比例是0.07473841554559044%

2.2 缺失值处理

面对缺失值,三种处理方法:不处理、删除以及填充

2.2.1 不处理

  1. 不涉及距离的算法(贝叶斯、xgboost、神经网络等)对缺失值不敏感;
  2. 有些字段对结果分析作用不大。

2.2.2 删除

在数据量比较大时候或者一条记录中多个字段缺失,不方便填补的时候可以选择删除缺失值

#axis= 0 代表'行','any'代表任何空值行,若是'all'则代表所有值都为空时,才删除该行
data.dropna(axis=0,how="any",inplace=True) 
#删除带有空值的行
data.dropna(axis=0,inplace=True) 
#删除带有空值的列
data.dropna(axis=1,inplace=True) 

2.2.3 填充

数据量较少时候,以最可能的值来插补缺失值

  1. 单变量插补
  2. 多变量插补

可以多种方法结合使用,如众数填充文本缺失,然后用适合的数字型插补填充其他

sklearn 通过对插值数据集打分选择合适插值方式

2.2.3.1 单变量插补
from sklearn.impute import SimpleImputer

详细参数介绍参考
sklearn 单变量API介绍

2.2.3.1.1 固定值填充

简单不实用,看看就行

#缺失值全部用0插补
data = data.fillna(0)   
#某列缺失值用固定值插补
data['col_name'] = data['col_name'].fillna('UNKNOWN')  
2.2.3.1.2 众数填充

离散/连续数据都行,特别适用于非数值变量,如性别

# mode返回出现最多的数据,col_name为列名
freq_port = data.col_name.dropna().mode()[0]  
#采用出现最频繁的值插补
data['col_name'] = data['col_name'].fillna(freq_port)   
# 功能函数 寻找 描述变量
def seek_object_column(df):
    """
        寻找描述变量列
        将其存储到cat_vars这个list中
    """
    cat_vars = []
    cols = df.columns.tolist()
    for col in cols:
        if df[col].dtype == 'object':
            cat_vars.append(col)
    return cat_vars
# sklearn 简易方式
imp = SimpleImputer(strategy='most_frequent')
cat_vars = seek_object_column(data_csv)
data_csv[cat_vars] = imp.fit_transform(data_csv[cat_vars])
data_csv.head()
agesexbmichildrensmokerregioncharges
019female27.9000.0yessouthwest16884.92400
118male33.7701.0nosoutheast1725.55230
228male33.0003.0nosoutheast4449.46200
333male22.7050.0nonorthwest21984.47061
432male28.8800.0nonorthwest3866.85520
2.2.3.1.3 中位数/均值填充

数值型数据
中位数:适用于偏态分布或者有离群点的分布
均值:适用于正态分布

#中位数插补
data['col_name'].fillna(data['col_name'].dropna().median(),inplace=True)  
# 均值插补
data['col_name'].fillna(data['col_name'].dropna().mean(),inplace=True)
# sklearn 简易方式
imp = SimpleImputer(strategy='mean')
data_num = imp.fit_transform(data_num)
# sklearn 简易方式
imp = SimpleImputer(strategy='median')
data_num = imp.fit_transform(data_num)
2.2.3.1.4 用前后数据填充

数值或字符串均可

 #用前一个数据填充
data['col_name'] = data['col_name'].fillna(method='pad')  
#用后一个数据填充
data['col_name'] = data['col_name'].fillna(method='bfill')  
2.2.3.1.5 拉格朗日插值法

一般针对有序的数据,如带有时间列的数据集,且缺失值为连续型数值小批量数据
(连续超过5个数据误差会很大,不建议用)

from scipy.interpolate import lagrange

def lagrange_fill(data):
    #自定义列向量插值函数,s为列向量,n为被插值的位置,k为取前后的数据个数,默认5
    def ployinterp_columns(s, n, k=5):
        y = s[list(range(n-k,n)) + list(range(n+1,n+1+k))]  #取数
        y = y[y.notnull()]  #剔除空值
        return lagrange(y.index, list(y))(n)    #插值并返回插值结果

    #逐个元素判断是否需要插值
    for i in data.columns:
        for j in range(len(data)):
            if (data[i].isnull())[j]:   #如果为空即插值
                data[i][j] = ployinterp_columns(data[i],j)
    return data

data = lagrange_fill(data_csv)
data.head()
C:\Users\Not a Literary Gaint\AppData\Local\Temp\ipykernel_19952\3195800559.py:14: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  data[i][j] = ployinterp_columns(data[i],j)
agesexbmichildrensmokerregioncharges
019female27.9000.0yessouthwest16884.92400
118male33.7701.0nosoutheast1725.55230
228male33.0003.0nosoutheast4449.46200
333male22.7050.0nonorthwest21984.47061
432male28.8800.0nonorthwest3866.85520
2.2.3.1.6 热卡插补

在完整数据中找到一个与它最相似的对象,用最相似的值填充当前值。
热卡填充其实就是使用KNN去预测的一种特殊形式,KNN是参考K个,而热卡填充是参考最近的1个。

from sklearn.impute import KNNImputer

详细参数介绍参考
sklearn 热卡插补API 介绍

imp = KNNImputer(n_neighbors=2, weights='uniform')
data_num = imp.fit_transform(data_num)
2.2.3.1.7 拟合插补

拟合插补法则是利用有监督的机器学习方法,
比如回归、最邻近、随机森林、支持向量机等模型,对缺失值作预测。
其优势在于预测的准确性高,缺点是需要大量的计算,导致缺失值的处理速度大打折扣。

回归插补

前提是 缺失值是连续的, 可以回归预测。
基于完整的数据集,建立回归方程。
对于包含空值的对象,将已知属性值代入方程来估计未知属性值,以此估计值来进行填充。当变量不是线性相关时会导致有偏差的估计。缺失值是连续的,即定量的类型,才可以使用回归来预测。

# 这里采用的是 Ridge 回归,也可以用其他回归
from sklearn.linear_model import Ridge
def lin_filled_func(x_train, y_train, test):
    # params: x_train 为不含缺失值的属性数据
    # params: y_train 为不含缺失值的标签数据
    # params: test 为已知的属性值,用来预测
    ridge = Ridge(alpha=0.01, max_iter=10000)
    ridge.fit(x_train, y_train)
    return ridge.predict(test)

最邻近填充

利用knn算法填充,其实是把目标列当做目标标量,利用非缺失的数据进行knn算法拟合,最后对目标列缺失进行预测。(对于连续特征一般是加权平均,对于离散特征一般是加权投票)。

KNN算法的详细介绍
sklearn KNN算法

from sklearn.neighbors import KNeighborsClassifier, KNeighborsRegressor

def knn_filled_func(x_train, y_train, test, k = 3, dispersed = True):
    # params: x_train 为目标列不含缺失值的数据(不包括目标列)
    # params: y_train 为不含缺失值的目标列
    # params: test 为目标列为缺失值的数据(不包括目标列)
    if dispersed:
        knn= KNeighborsClassifier(n_neighbors = k, weights = "distance")
    else:
        knn= KNeighborsRegressor(n_neighbors = k, weights = "distance")
    
    knn.fit(x_train, y_train)
    return test.index, knn.predict(test)

随机森林插补

随机森林算法填充的思想和knn填充是类似的,即利用已有数据拟合模型,对缺失变量进行预测。

随机森林详细介绍可参考
集成方法 的 树类API

from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier

def forest_filled_func(x_train, y_train, test, k = 3, dispersed = True):
    # params: x_train 为目标列不含缺失值的数据(不包括目标列)
    # params: y_train 为不含缺失值的目标列
    # params: test 为目标列为缺失值的数据(不包括目标列)
    if dispersed:
        rf= RandomForestRegressor()
    else:
        rf= RandomForestClassifier()
    
    rf.fit(x_train, y_train)
    return test.index, rf.predict(test)

其他拟合方法类似,这里不再赘述。

2.2.3.2 多变量插补

多重插补(Mutiple imputation,MI)的思想来源于贝叶斯估计,认为待插补的值是随机的,它的值来自于已观测到的值。具体实践上通常是估计出待插补的值,然后再加上不同的噪声,形成多组可选插补值。根据某种选择依据,选取最合适的插补值。

详细参数介绍参考
sklearn多重插补 API介绍
sklearn多重插补 不同估算器比较

from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
imp = IterativeImputer(max_iter=10, random_state=0)
data_num = imp.fit_transform(data_num)

3. 异常值

异常值是指样本中的个别值,其数值明显偏离它所属样本的其余观测值。
异常值有时是记录错误或者其它情况导致的错误数据,有时是代表少数情况的正常值。

3.1 异常值识别

3.1.1 描述性统计法

与业务或者基本认知不符的数据,如年龄为负;
即根据属性值自身的范围进行筛选。

neg_list = ['col_name_1','col_name_2','col_name_3']
# 这里以 大于0 为 筛选条件(其他筛选条件可以根据实际情况照例编写)
# 可以先打印,在筛选
# 小于零的打印结果
for item in neg_list:
    neg_item = data[item] < 0
    print(item + '小于0的有' + str(neg_item.sum())+'个')

#删除小于0的记录
for item in neg_list:
    data = data[(data[item]>=0)]
    
# 或者根据条件直接筛选    
# 列名1 指标 <800 且 列名2 指标 >600 的数据
data = data[(data['col_name_1'] < 800) & (data['col_name_2'] > 600)]

# 多个条件也类似

这个套路可以根据确定的条件无限筛选出想要的数据,注意每个独立的小条件都要有括号 ‘( )’

3.1.2 三σ法

# 检测正态分布的 API
from scipy.stats import kstest

当数据服从正态分布时,
99.7%的数值应该位于距离均值3个标准差之内的距离:P(|x−μ|>3σ)≤0.003
超出这个范围即可认为它为异常值

def KsNormDetect(df, col_name):
    """
        检测是否符合正太分布
    """
    # 计算均值
    u = df[col_name].mean()
    # 计算标准差
    std = df[col_name].std()
    # 计算P值
    res=kstest(df[col_name], 'norm', (u, std))[1]
    # 判断p值是否服从正态分布,p<=0.05 则服从正态分布,否则不服从。
    if res<=0.05:
        print('该列数据服从正态分布------------')
        print('均值为:%.3f,标准差为:%.3f' % (u, std))
        print('------------------------------')
        return 1
    else:
        return 0



def OutlierDetection(df, col_name, ks_res):
    """
        异常值检测与剔除
    """
    # 计算均值
    u = df[col_name].mean()
    # 计算标准差
    std = df[col_name].std()
    if ks_res==1:
        # 定义3σ法则识别异常值
        # 识别异常值
        error = df[np.abs(df['value'] - u) > 3 * std]
        # 剔除异常值,保留正常的数据
        data_c = df[np.abs(df['value'] - u) <= 3 * std]
        # 输出异常数据
        print('检测到的异常值如下---------------------')
        display(error)
        return data_c

    else:
        print('请先检测数据是否服从正态分布-----------')
        return None


if __name__ == '__main__':
    # 创建数据
    data = [1222, 87, 77, 92, 68, 80, 78, 
            84, 77, 81, 80, 80, 77, 92, 86, 
            76, 80, 81, 75, 77, 72, 81, 72, 
            84, 86, 80, 68, 77, 87, 76, 77, 
            78, 92, 75, 80, 78, 123, 3, 1223, 1232]
    df = pd.DataFrame(data, columns=['value'])
    ks_res=KsNormDetect(df, 'value')
    df = OutlierDetection(df, 'value',ks_res)
该列数据服从正态分布------------
均值为:164.850,标准差为:306.289
------------------------------
检测到的异常值如下---------------------
value
01222
381223
391232

3.1.3 Z-score 异常值检测

zscore和3∂原则的计算思路相同且需要数据符合正态分布,计算公式是:
Z i    =    x i       −    μ σ Z_i\,\,=\,\,\frac{x_{i\,\,}\,\,-\,\,\mu}{\sigma} Zi=σxiμ
其中 xi 是一个数据点,μ 是所有点 xi 的平均值,δ 是所有点 xi 的标准偏差。
threshold 一般为 2.5 ,3.0 ,3.5

def KsNormDetect(df, col_name):
    """
        检测是否符合正太分布
    """
    # 计算均值
    u = df[col_name].mean()
    # 计算标准差
    std = df[col_name].std()
    # 计算P值
    res=kstest(df[col_name], 'norm', (u, std))[1]
    # 判断p值是否服从正态分布,p<=0.05 则服从正态分布,否则不服从。
    if res<=0.05:
        print('该列数据服从正态分布------------')
        print('均值为:%.3f,标准差为:%.3f' % (u, std))
        print('------------------------------')
        return 1
    else:
        return 0

# threshold 一般为 2.5 ,3.0 ,3.5
def zscore_check(df,colname,threshold=3):
    if ks_res==1:
        # 取出数据
        data = df[colname]
        # 计算均值
        u = data.mean()
        # 计算标准差
        std = data.std()
        # 计算得分
        zscore = (data - u) / (std)
        # 打印异常值
        error = df[zscore.abs() > threshold]
        print('检测到的异常值如下---------------------')
        display(error)
        return df[zscore.abs() <= threshold]
    else:
        print('请先检测数据是否服从正态分布-----------')
        return None

if __name__ == '__main__':
    # 创建数据
    data = [1222, 87, 77, 92, 68, 80, 78, 
            84, 77, 81, 80, 80, 77, 92, 86, 
            76, 80, 81, 75, 77, 72, 81, 72, 
            84, 86, 80, 68, 77, 87, 76, 77, 
            78, 92, 75, 80, 78, 123, 3, 1223, 1232]
    df = pd.DataFrame(data, columns=['value'])
    ks_res=KsNormDetect(df, 'value')
    df = zscore_check(df, 'value',ks_res)
该列数据服从正态分布------------
均值为:164.850,标准差为:306.289
------------------------------
检测到的异常值如下---------------------
value
01222
381223
391232

3.1.4 基于MAD的Z-score 异常值检测

MAD为(Mean Absolute Deviation,中位数绝对偏差),是单变量数据集中样本差异性的统计量,比标准差更有弹性,它的计算公式是:
M A D    =    ∑ i = 1 n    ∣ x i    −    x ˉ ∣ n    x i    : i 期的实际值 , x ˉ    : 平均值 , n    : 数据值 MAD\,\,=\,\,\frac{\sum_{i=1}^n{\,\,|x_i\,\,-\,\,\bar{x}|}}{n}\,\, \\ x_i\,\,: i\text{期的实际值}, \bar{x}\,\,: \text{平均值}, n\,\,: \text{数据值} MAD=ni=1nxixˉxi:i期的实际值,xˉ:平均值,n:数据值

推理过程,根据推理,我们得到一个结果:MAD 约等于 0.6745*δ , 比较利于编程。
同样的, threshold 一般设置为 2.5 3.0 3.5

def KsNormDetect(df, col_name):
    """
        检测是否符合正太分布
    """
    # 计算均值
    u = df[col_name].mean()
    # 计算标准差
    std = df[col_name].std()
    # 计算P值
    res=kstest(df[col_name], 'norm', (u, std))[1]
    # 判断p值是否服从正态分布,p<=0.05 则服从正态分布,否则不服从。
    if res<=0.05:
        print('该列数据服从正态分布------------')
        print('均值为:%.3f,标准差为:%.3f' % (u, std))
        print('------------------------------')
        return 1
    else:
        return 0

# threshold 一般为 2.5 ,3.0 ,3.5
def zscore_check(df,colname,threshold=3.5):
    if ks_res==1:
        # 取出数据
        data = df[colname]
        # 计算 MAD
        MAD = (data - data.median()).abs().median()
        # 计算得分
        zscore = ((data - data.median())*0.6475 / MAD)
        # 打印异常值
        error = df[zscore.abs() > threshold]
        print('检测到的异常值如下---------------------')
        display(error)
        return df[zscore.abs() <= threshold]
    else:
        print('请先检测数据是否服从正态分布-----------')
        return None

if __name__ == '__main__':
    # 创建数据
    data = [1222, 87, 77, 92, 68, 80, 78, 
            84, 77, 81, 80, 80, 77, 92, 86, 
            76, 80, 81, 75, 77, 72, 81, 72, 
            84, 86, 80, 68, 77, 87, 76, 77, 
            78, 92, 75, 80, 78, 123, 3, 1223, 1232]
    df = pd.DataFrame(data, columns=['value'])
    ks_res=KsNormDetect(df, 'value')
    df = zscore_check(df, 'value',ks_res)
该列数据服从正态分布------------
均值为:164.850,标准差为:306.289
------------------------------
检测到的异常值如下---------------------
value
01222
187
392
468
1392
2072
2272
2668
2887
3292
36123
373
381223
391232

3.1.5 数据倾斜处理(偏度)

数据倾斜,指的是并行处理的过程中,
某些分区或节点处理的数据,显著高于其他分区或节点,
导致这部分的数据处理任务比其他任务要大很多,从而成为这个阶段执行最慢的部分,
进而成为整个作业执行的瓶颈,甚至直接导致作业失败。

# 检测倾斜API
from scipy import stats
def skew_check(df):
    """
        检测倾斜
        如果值大于1,则证明存在倾斜;
        值越接近于0,越趋近于平缓。
        返回: 倾斜的列名
        
    """
    skew_attention = []
    for column in df.columns:
        if (df[column].dtype == 'int64') or (df[column].dtype == 'float64'):
            skew = stats.mstats.skew(df[column]).data
            if skew >= 1:
                skew_attention.append(column)
    print('检测到的倾斜的列名如下---------------------')
    print(skew_attention)
    return skew_attention

def skew_process(df, skew_attention):
    """
        处理倾斜
    """
    for column in skew_attention:
        df[column] = np.log(df[column])
    return df

if __name__ == '__main__':
    # 创建数据
    data = [1222, 87, 77, 92, 68, 80, 78, 
            84, 77, 81, 80, 80, 77, 92, 86, 
            76, 80, 81, 75, 77, 72, 81, 72, 
            84, 86, 80, 68, 77, 87, 76, 77, 
            78, 92, 75, 80, 78, 123, 3, 1223, 1232]
    df = pd.DataFrame(data, columns=['value'])
    skew_attention = skew_check(df)
    df = skew_process(df, skew_attention)
    display(df.head())
检测到的倾斜的列名如下---------------------
['value']
value
07.108244
14.465908
24.343805
34.521789
44.219508

3.1.6 箱型图

当数据不符合正态分布, 可以使用箱型图检测异常值(符合也可以用)

def OutlierDetection(df, colname):
    # 计算下四分位数和上四分位
    Q1 = df[colname].quantile(q=0.25)
    Q3 = df[colname].quantile(q=0.75)

    # 基于1.5倍的四分位差计算上下须对应的值
    low_whisker = Q1 - 1.5 * (Q3 - Q1)
    up_whisker = Q3 + 1.5 * (Q3 - Q1)

    # 寻找异常点
    kk = df[(df[colname] > up_whisker) | (df[colname] < low_whisker)]
    df = df[(df[colname] <= up_whisker) & (df[colname] >= low_whisker)]
    print('箱线图检测到的异常值如下---------------------')
    display(kk)
    return df



if __name__ == '__main__':
    # 创建数据
    data = [1222, 87, 77, 92, 68, 80, 78, 
            84, 77, 81, 80, 80, 77, 92, 86, 
            76, 80, 81, 75, 77, 72, 81, 72, 
            84, 86, 80, 68, 77, 87, 76, 77, 
            78, 92, 75, 80, 78, 123, 3, 1223, 1232]
    df = pd.DataFrame(data, columns=['value'])
    result = OutlierDetection(df, 'value')
    display(result.head())
箱线图检测到的异常值如下---------------------
value
01222
36123
373
381223
391232
value
187
277
392
468
580

3.1.7 其它

基于聚类方法检测、基于密度的离群点检测、基于近邻度的离群点检测等。
(类似于缺失值拟合方法,调用sklearn的聚类方法对每列聚类,挑出离群点,这里不再赘述)

4. 类别特征编码

大部分机器学习算法要求输入的数据必须是数字,
这就要求将数据中的描述性变量(如性别)转换为数值型数据

有序编码 和 无序one-hot编码

from sklearn import preprocessing
def seek_object_column(df):
    """
        寻找描述变量列
        将其存储到cat_vars这个list中
    """
    cat_vars = []
    print('\n描述变量有:')
    cols = df.columns.tolist()
    for col in cols:
        if df[col].dtype == 'object':
            print(col)
            cat_vars.append(col)
    return cat_vars

def transform_object_to_num(data, cat_vars, ordered=False):
    """
        转化描述变量列
        ordered 划分数据为 有序 与 无序
        有序 分类为 0-n
        无序 分类为 one-hot 编码, 即 0,1
    """  
    print('\n开始转换描述变量...')
    le = preprocessing.LabelEncoder()
    if ordered:
        ##若变量是有序的##   
        #将描述变量自动转换为数值型变量,并将转换后的数据附加到原始数据上
        for col in cat_vars:
            tran = le.fit_transform(data[col].tolist())
            tran_df = pd.DataFrame(tran,columns=['num_'+col])
            print('{col}经过转化为{num_col}'.format(col=col,num_col='num_'+col))
            data = pd.concat([data, tran_df], axis=1)
            del data[col]  #删除原来的列
    else:
        ##若变量是无序变量## 
        #值得注意的是one-hot可能引发维度爆炸
        for col in cat_vars:
            onehot_tran = pd.get_dummies(data[col])
            data = data.join(onehot_tran)  #将one-hot后的数据添加到data中
            del data[col]  #删除原来的列
    print('\n输出编码后的DataFrame:')
    display(data.head())
    return data


cat_vars = seek_object_column(data)
data = transform_object_to_num(data, cat_vars)
描述变量有:
sex
smoker
region

开始转换描述变量...

输出编码后的DataFrame:
agebmichildrenchargesfemalemalenoyesnortheastnorthwestsoutheastsouthwest
01927.9000.016884.9240010010001
11833.7701.01725.5523001100010
22833.0003.04449.4620001100010
33322.7050.021984.4706101100100
43228.8800.03866.8552001100100

5. 数据连续属性离散化

可以为分层抽样时提供比例参考

一些数据挖掘算法,别是分类算法,要求数据是分类属性形式。常常需要将连续属性变换成分类属性,即连续属性离散化。 常用的离散化方法:

  1. 等宽法:
    将属性值域分成具有相同宽度的区间,区间的个数由数据本身的特点决定,或者由用户指定,类似于制作频率分布表。
  2. 等频法:
    将相同数量的记录放进每个区间。
  3. 基于聚类分析的方法:
    通过分箱离散化、通过直方图分析离散化、通过聚类、决策树和相关分析离散化、标称数据的概念分层产生。

前两种方法简单易操作,但需要人为规划区间,且等宽法对离群点敏感,容易分的不均,而等频法为了平均会把相同的分到不同区间,干扰决策。

cut 参数介绍

pd.cut( x, bins, right=True, 
       labels=None, retbins=False, precision=3, 
       include_lowest=False, duplicates='raise', ordered=True)
  1. x:待分箱 一维数组
  2. bins:
    1. 整数 则表示将x中的数值分成等宽的n份
    2. 标量序列 序列中的数值表示用来分档的分界值 [1, 2, 3, 4]
    3. 间隔索引 元组内的分界 如(0, 2), (3, 6)
  3. right:是否包含bins区间的最右边,默认为True,最右边为闭区间,False则不包含
  4. labels:指定返回的 bins 的标签 当bins为 间隔索引时, 忽略此参数
  5. retbins:是否返回bins的分组依据,默认为False
  6. precision:小数点位数 参数为 0 和 1 时一样
  7. include_lowest:是否包含最左边,左闭包 默认为False
  8. duplicates:{‘raise’, ‘drop’} drop去除bins里的重复分界
  9. ordered:需要配合labels一起使用 形成有序分类
# 画图
def classified_plot(data, d, k):
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.figure(figsize=(7,5))
    for j in range(0, k):
        plt.plot(data[d==j], [i for i in d[d==j]], 'o')
# 例子加载
data = pd.read_excel(r'../../data/practice/discretization_data.xls')
data = data['肝气郁结证型系数'].copy()  #将数据集转化为集合
k = 4    #k值为组数

5.1 等宽法

def cut_bins_width(data, k):
    """
        每组的宽度相同
        处理单位为某一列
    """
    d1 = pd.cut(data,k,labels=range(k))   #将集合分组
    print('数值分布图---------')
    classified_plot(data, d1, k)
    plt.show()
    print('数量分布图---------')
    display(d1.hist())
    plt.show()
    return d1

d1 = cut_bins_width(data, k)
数值分布图---------

在这里插入图片描述

数量分布图---------



<AxesSubplot:>

在这里插入图片描述

5.2 等频法

def cut_bins_freq(data, k):
    """
        每组的数量相同
        处理单位为某一列
    """
    w = [i/k for i in range(k+1)] #计算百分比
    w = data.describe(percentiles=w)[4:4+k+1]  #计算各个百分位数
    w[0] = w[0]*(1-1e-10)
    d2 = pd.cut(data,w,labels=range(k))   #将集合分组
    print('数值分布图---------')
    classified_plot(data, d2, k)
    plt.show()
    print('数量分布图---------')
    display(d2.hist())
    plt.show()
    return d2

d2 = cut_bins_freq(data, k)
数值分布图---------

在这里插入图片描述

数量分布图---------



<AxesSubplot:>

在这里插入图片描述

5.3 k-means分组

from sklearn.cluster import KMeans   #导入kmeans
def cut_bins_k_means(data, k):
    """
        聚类分组
        处理单位为某一列
    """
    kmodel = KMeans(n_clusters = k)      #确定族数
    kmodel.fit(data.values.reshape(len(data),1))    #训练数据集
    c = pd.DataFrame(np.sort(kmodel.cluster_centers_))   #确定中心并排序
    w = c.rolling(2).mean().iloc[1:]      #取移动平均值
    w = [0]+list(w[0])+[data.max()]       #加上最大最小值作为边界值
    w = list(np.sort(w))          #再次排序
    d3 = pd.cut(data,w,labels = range(k))
    print('数值分布图---------')
    classified_plot(data, d3, k)
    plt.show()
    print('数量分布图---------')
    display(d3.hist())
    plt.show()
    return d3

d3 = cut_bins_k_means(data, k)
数值分布图---------

在这里插入图片描述

数量分布图---------



<AxesSubplot:>

在这里插入图片描述

6. 训练集测试集划分

# 例子加载
house_data = pd.read_csv(r'../../data/practice/housing.csv')

6.1 随机抽样

适用于庞大数据集
(样本个数远远大于属性个数)

from sklearn.model_selection import train_test_split
# 提供了随机种子 可以确定随机顺序 
# 但数据的顺序如果更新,仍会变化,故仅解决在重复运行同一数据集的随机唯一性
# 参数 1.数据 2.比例 3.随机种子
train_set, test_set = train_test_split(data, test_size=0.2, random_state=42)

6.2 分层抽样

中小数据集抽样需要重要属性分层比例合理
如 人口男女比例 6:4,为了调查结果符合全体人口,
在只有 1000 人样本时 在抽取时会希望测试 和 训练 都满足 6:4 这个比例,
则需要将数据均匀划分层次, 每层抽取正确样本数量, 来确保测试 和 训练集合有这个比例

1. 如果之前分过层,不需要再分,直接使用属性作为分层依据即可。
分层使用先前的离散方法分层(3种任选一种)

from sklearn.cluster import KMeans   #导入kmeans
def cut_bins_k_means(data, k):
    """
        聚类分组
        处理单位为某一列
    """
    kmodel = KMeans(n_clusters = k)      #确定族数
    kmodel.fit(data.values.reshape(len(data),1))    #训练数据集
    c = pd.DataFrame(np.sort(kmodel.cluster_centers_))   #确定中心并排序
    w = c.rolling(2).mean().iloc[1:]      #取移动平均值
    w = [0]+list(w[0])+[data.max()]       #加上最大最小值作为边界值
    w = list(np.sort(w))          #再次排序
    d3 = pd.cut(data,w,labels = range(k))
    print('数值分布图---------')
    classified_plot(data, d3, k)
    plt.show()
    print('数量分布图---------')
    display(d3.hist())
    plt.show()
    return d3

house_data['income_cat'] = cut_bins_k_means(house_data['median_income'], 4)
house_data.head()
数值分布图---------

在这里插入图片描述

数量分布图---------



<AxesSubplot:>

在这里插入图片描述

longitudelatitudehousing_median_agetotal_roomstotal_bedroomspopulationhouseholdsmedian_incomemedian_house_valueocean_proximityincome_cat
0-122.2337.8841.0880.0129.0322.0126.08.3252452600.0NEAR BAY3
1-122.2237.8621.07099.01106.02401.01138.08.3014358500.0NEAR BAY3
2-122.2437.8552.01467.0190.0496.0177.07.2574352100.0NEAR BAY3
3-122.2537.8552.01274.0235.0558.0219.05.6431341300.0NEAR BAY2
4-122.2537.8552.01627.0280.0565.0259.03.8462342200.0NEAR BAY0

2. sklearn 分层抽样

from sklearn.model_selection import StratifiedShuffleSplit
# 分层抽样
# 参数: 1. 训练和测试组的对数  2. 测试集在每对的比例  3. 随机种子 
split = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
# split(分类数据, 类别依据)
for train_index, test_index in split.split(house_data, house_data['income_cat']):
    stra_train_set = house_data.loc[train_index]
    stra_test_set = house_data.loc[test_index]

3. 查验比例 与 比例偏差

def check_attribute_ratio(data, reference_col):
    """
    查验属性比例
    参数: data 数据
          reference_col 类别依据
    """
    return data[reference_col].value_counts() / len(data)

def ratio_error(overall_ratio, com_ratio):
    """
    返回比例偏差
    参数: 原始数据的比例
          需要比较的数据比例
    """
    return np.abs(com_ratio - overall_ratio.values)


## 比例依据
reference_col = 'income_cat'

## 属性比例比例
# 总体
overall_ratio = check_attribute_ratio(house_data, reference_col)
# 分层抽样
stratified_test_ratio = check_attribute_ratio(stra_test_set, reference_col)
stratified_train_ratio = check_attribute_ratio(stra_train_set, reference_col)

## 比例偏差
# 分层抽样
stratified_test_error = ratio_error(overall_ratio, stratified_test_ratio)
stratified_train_error = ratio_error(overall_ratio, stratified_train_ratio)

## df 打印
ratio_df = pd.DataFrame({
    '总体':overall_ratio,
    '测试分层':stratified_test_ratio,
    '训练分层':stratified_train_ratio,
    '测试偏差分层':stratified_test_error,
    '训练偏差分层':stratified_train_error,
})
display(ratio_df)
总体测试分层训练分层测试偏差分层训练偏差分层
00.6448160.6448640.6448040.0000480.000012
20.1672970.1673930.1672720.0000970.000024
10.1340600.1339630.1340840.0000970.000024
30.0538280.0537790.0538400.0000480.000012

4. 删除分层属性,恢复数据原样

for set_ in (stra_train_set, stra_test_set):
    set_.drop('income_cat', axis=1, inplace=True)

6.3 分割标签和属性

def split_labels_attribute(df, label):
    """
        分割标签与属性
        df 数据集
        label 标签名称
    """
    x = df.drop(label, axis=1)
    y = df[label]
    return x, y
# 这里以 charges 为标签
train_x, train_y = split_labels_attribute(train_set, 'charges')
test_x, test_y = split_labels_attribute(test_set, 'charges')

7.数据规范化(归一化)

数据的标准化(normalization)是将数据按比例缩放,使之落入一个小的特定区间。
去除数据的单位限制,将其转化为无量纲的纯数值,便于不同单位或量级的指标能够进行比较和加权。

一些需要数据归一化的算法:
LR、SVM、KNN、KMeans、AdaBoost、神经网络等,
一些不需要数据归一化的算法:
树形模型(决策树 DT、随机森林 RF、GBDT等)原因

注意

  1. 没有一种数据标准化的方法是万能的,对于不同的问题有不同的归一化方法。
  2. 先划分 测试集 与 训练集,再归一化。
  3. 标签 y 也可以归一化,具体是否实施措施看效果, 暂时没有找到相关介绍论文,
    现在可以参考一下:一些浅显的解释

7.1 最大最小值归一化

对原始数据进行线性变换,变换到[0,1]区间。
计算公式为:x* = (x-x.min)/(x.max-x.min)

它的特点是不会对数据分布产生影响。
不过如果你的数据的最大最小值不是稳定的话,即异常值多,结果可能因此变得不稳定,不建议用。
min-max 归一化在图像处理上非常常用,因为大部分的像素值范围是 [0, 255]。

使用建议

  1. 对处理后的数据范围有严格要求,建议使用;
  2. 数据存在异常值和较多噪音,此时归一化受异常值影响,不建议使用;
  3. 在不涉及距离度量、协方差计算以及数据不符合正太分布的时候,建议使用。
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
# 最大最小值归一化
train_x_sca = scaler.fit_transform(train_x)
test_x_sca = scaler.fit_transform(test_x)

7.2 标准归一化

对原始数据进行线性变换,经过处理的数据的均值为0,标准差为1。
计算方式是将特征值减去均值,除以标准差,计算公式为:x* = (x-x.mean)/σ

使用建议

  1. 如果数据存在异常值和较多噪音,用标准化,可以间接通过中心化避免异常值和极端值的影响
  2. 在分类、聚类算法中,需要使用距离来度量相似性的时候、或者使用PCA技术进行降维的时候,建议使用。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
# 标准归一化
train_x_sca = scaler.fit_transform(train_x)
test_x_sca = scaler.transform(test_x)

7.3 其他归一化

  1. 缩放稀疏数据
    中心化稀疏数据会破坏数据的稀疏结构,因此明智的做法是少做这样的操作。但是,缩放稀疏输入是有意义的,尤其是当特征处于不同的缩放比例时。
  2. 缩放包含离群值的数据
    如果数据中包含许多离群值,使用数据的均值和方差进行缩放可能效果不佳。

这一部分建议参考 sklearn归一化处理的 6.3.1.2 和 6.3.1.3:
sklearn归一化处理详细介绍

8. 降维

8.1 PCA主成分分析

用于连续属性的数据降维方法,旨在用少量新变量解释原数据,即主要成分。

sklearn PCA API介绍
PCA以及其他降维方式详解

from sklearn.decomposition import PCA

先默认看一下贡献率

pca = PCA()
pca.fit(train_x_sca)
print('\n模型的各个特征向量')
print(pca.components_)
print('\n返回各成分的方差百分比(贡献率)')
print(pca.explained_variance_ratio_)
模型的各个特征向量
[[-7.94175895e-03  3.74633341e-03  6.39264528e-03 -6.97717175e-01
   6.97717175e-01 -1.12968712e-01  1.12968712e-01  8.18634362e-03
   1.46567874e-02 -1.49902201e-03 -2.13441090e-02]
 [-3.97575557e-02  9.84301203e-03  1.29919942e-03  1.10198731e-01
  -1.10198731e-01 -6.76425713e-01  6.76425713e-01  1.73896789e-02
  -1.03723489e-01  1.91730067e-01 -1.05396257e-01]
 [ 6.45653175e-03  8.86642610e-02 -1.10589566e-02 -2.30937710e-02
   2.30937710e-02  1.26600910e-01 -1.26600910e-01 -5.16825809e-01
  -1.26710225e-01  8.05823140e-01 -1.62287106e-01]
 [ 2.02356991e-02  1.52902430e-02  5.14718495e-03  8.81588025e-04
  -8.81588025e-04 -9.70362187e-02  9.70362187e-02 -5.94698021e-01
   2.22603820e-02 -1.94662109e-01  7.67099748e-01]
 [ 5.72080699e-03 -2.49922743e-02  1.78304459e-02  2.19337811e-02
  -2.19337811e-02 -5.92527445e-02  5.92527445e-02 -3.55518143e-01
   8.49129901e-01 -1.42403404e-01 -3.51208354e-01]
 [ 9.90879493e-01  8.45935423e-02  9.38143287e-02 -4.50515403e-04
   4.50515403e-04 -2.60483409e-02  2.60483409e-02  2.22934354e-02
  -7.16646949e-03  1.93464043e-03 -1.70616064e-02]
 [-9.19797753e-02 -2.33027225e-02  9.95193738e-01  3.65456884e-03
  -3.65456884e-03  7.06454162e-03 -7.06454162e-03  7.81408476e-04
  -1.65834798e-02  1.33382145e-02  2.46385679e-03]
 [-8.70052799e-02  9.91700680e-01  1.67039878e-02  4.27019303e-03
  -4.27019303e-03 -1.78753556e-03  1.78753556e-03  4.43302523e-02
   3.35805238e-02 -7.43820142e-02 -3.52876196e-03]
 [ 5.13513206e-18 -2.06812965e-16  3.87942933e-17  7.75905231e-03
   7.75905231e-03  4.99511115e-02  4.99511115e-02 -4.98720705e-01
  -4.98720705e-01 -4.98720705e-01 -4.98720705e-01]
 [ 5.87317919e-17 -3.83141025e-16  2.62054152e-16  5.67971427e-02
   5.67971427e-02  7.03016694e-01  7.03016694e-01  3.56483668e-02
   3.56483668e-02  3.56483668e-02  3.56483668e-02]
 [ 1.18663144e-17  1.89796899e-16  9.82757689e-17  7.04779314e-01
   7.04779314e-01 -5.72050172e-02 -5.72050172e-02  2.61766290e-03
   2.61766290e-03  2.61766290e-03  2.61766290e-03]]

返回各成分的方差百分比(贡献率)
[2.89006618e-01 1.87154310e-01 1.48296902e-01 1.41500700e-01
 1.38274884e-01 5.38189695e-02 2.81985615e-02 1.37490544e-02
 4.82189608e-32 1.79450230e-32 1.11931405e-32]

根据贡献率 调整主成分个数 重新建立模型

# 上述看到 8 个基本就接近 90% 以上
pca = PCA(8)
pca.fit(train_x_sca)

# 降维
low_d = pca.transform(train_x_sca) 
new_data = pd.DataFrame(low_d) # df 打印
display(new_data)
01234567
0-0.747525-0.281572-0.138311-0.0120500.8679880.1158120.146058-0.254364
1-0.756073-0.160642-0.513806-0.628659-0.3460140.142346-0.206365-0.135041
2-0.7665670.0095200.810833-0.226201-0.1326400.230921-0.204145-0.248803
3-0.7575070.0244520.821433-0.223309-0.1242670.0584500.7285420.043498
4-0.747581-0.287845-0.135591-0.0069620.8712320.3088050.311633-0.225878
...........................
1065-0.745668-0.132763-0.509220-0.634748-0.341266-0.3975150.5773130.119626
1066-0.7585600.0216850.796506-0.227607-0.1172400.0346670.735093-0.235309
10670.637549-0.390321-0.464035-0.625232-0.3890880.382143-0.236206-0.141575
1068-0.5532481.084707-0.3623970.934277-0.2335550.0270740.1516380.466830
10690.609012-0.509262-0.0986460.737190-0.3883290.288919-0.231487-0.057696

1070 rows × 8 columns

# 必要时可以 逆向 PCA
old_data = pca.inverse_transform(low_d)
old_data = pd.DataFrame(old_data) # df 打印
display(old_data)
012345678910
06.086957e-010.1073450.4497821.000000e+005.551115e-161.000000e+006.106227e-164.163336e-161.000000e+00-2.775558e-16-3.330669e-16
16.304348e-010.2249130.0829691.000000e+009.992007e-161.000000e+002.220446e-161.000000e+00-1.387779e-16-4.440892e-163.608225e-16
27.391304e-010.2394400.0829691.000000e+007.771561e-161.000000e+00-7.216450e-16-5.828671e-16-9.159340e-161.000000e+00-2.498002e-16
34.565217e-010.4939471.0000001.000000e+002.220446e-161.000000e+00-9.159340e-16-4.163336e-16-7.216450e-161.000000e+00-1.942890e-16
47.826087e-010.1482380.6331881.000000e+006.661338e-161.000000e+006.106227e-164.163336e-161.000000e+00-3.330669e-16-3.330669e-16
....................................
10652.220446e-160.4140440.8165941.000000e+006.661338e-161.000000e+001.110223e-161.000000e+00-2.775558e-17-2.775558e-163.608225e-16
10664.565217e-010.2128061.0000001.000000e+003.330669e-161.000000e+00-9.436896e-16-4.440892e-16-7.216450e-161.000000e+00-1.942890e-16
10678.695652e-010.2479150.0829691.665335e-161.000000e+001.000000e+002.775558e-161.000000e+00-1.110223e-16-4.440892e-161.110223e-16
10684.130435e-010.8512240.4497821.000000e+005.551115e-166.661338e-161.000000e+00-2.775558e-171.942890e-16-9.436896e-161.000000e+00
10698.043478e-010.3750340.0829695.551115e-161.000000e+001.000000e+007.494005e-166.938894e-16-6.938894e-16-2.220446e-161.000000e+00

1070 rows × 11 columns

这样就降低到 8 个维度,或者 利用降维知道前 8 个维度是主要影响因子。

9. 升维

9.1 升维本质

产生更多的特征角度去学习,提高模型的准确度,解决欠拟合的问题。

9.2 升维常见手段 (多项式回归)

已知维度 相乘 获取新的维度。

为何叫回归?
主要在回归任务中用的比较多,
且当 x 和 y 存在不存在线性关系,要训练模型,可以选择非线性算法去拟合数据;也可以选择升维 将数据变为线性关系后 继续使用线性算法,毕竟线性算法运算速度快一些。

9.3 升维代码实现 (多项式回归)

sklearn PolynomialFeatures API 详细介绍

from sklearn.preprocessing import PolynomialFeatures

X = np.arange(6).reshape(3, 2)
print(X)
>>> array([[0, 1],
	       [2, 3],
	       [4, 5]])
	       
# degree 参数 多项式特征的程度
poly = PolynomialFeatures(degree=2)
poly.fit_transform(X)
>>> array([[ 1.,  0.,  1.,  0.,  0.,  1.],
	       [ 1.,  2.,  3.,  4.,  6.,  9.],
	       [ 1.,  4.,  5., 16., 20., 25.]])

可以看出 特征 X    已经从 ( X 1 , X 2 )    转化为 ( 1 , X 1 , X 2 , X 1 2 , X 1 X 2 , X 2 2 ) \text{特征}X\,\,\text{已经从} \left( X_1, X_2 \right) \,\,\text{转化为}\left( 1, X_1, X_2, X_{1}^{2}, X_1X_2, X_{2}^{2} \right) 特征X已经从(X1,X2)转化为(1,X1,X2,X12,X1X2,X22)

更多详细用法,可参考 sklearn 6.3.7 生成多项式特征

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值