Python数据挖掘学习12特征的预处理(总)

67 篇文章 11 订阅
16 篇文章 0 订阅

特征工程指的是把原始数据转变为模型的训练数据的过程,它的目的就是获取更好的训练数据特征,使得机器学习模型逼近这个上限。特征工程能使得模型的性能得到提升,有时甚至在简单的模型上也能取得不错的效果。

  “数据决定了机器学习的上限,而算法只是尽可能逼近这个上限”,说明了数据的质量和数量是非常关键的,甚至比算法本身更重要,例如:如果做一个识别猫的,如果能把所以猫的图片都收集了,那么不需要算法就可以识别,当然这个比较极端的情况,也是不可能实现的。

 

数据样本采集(抽样)注意一下三点:

1.样本要具有代表性

2.样本比例要平衡以及样本不平衡时如何处理

3.考虑全量数据

异常值(空值)处理

识别异常值和重复值
Pandas:isnull()/duplicated()

直接丢弃(包括重复数据)
Pandas:drop()/dropna()/drop_duplicated()

把异常当作一个新的属性,替代原值
Pandas:fillna()

集中值指代
Pandas:fillna()

边界值指代
Pandas:fillna()

插值

Pandas:interpolate() --- Series

实际操作代码:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import math
df = pd.DataFrame({"A": ["a0", "a1", "a1", "a2", "a3", "a4"],
                   "B": ["b0", "b1", "b2", "b2", "b3", None],
                   "C": [1, 2, None, 3, 4, 5],
                   "D": [0.1, 10.2, 11.4, 8.9, 9.1, 12],
                   "E": [10, 19, 32, 25, 8, None],
                   "F": ["f0", "f1", "g2", "f3", "f4", "f5"]})
#去除空值
df.isnull()
#指定去除某一行的空值
df.dropna(subset=["B","C"])
#重复值,keep设定保留值,两个重复值留第一个
df.duplicated(["A"],keep="first")
#AB同时重复
df.drop_duplicates(["A","B"],keep="first",inplace=False)
#异常值替换,指定值
df["B"].fillna("b*")
#填补均值,会自动忽略异常值
df["E"].fillna(df["E"].mean())
#插值方法
df["E"].interpolate(method="spline",order=3)
#插入,相邻值之和/个数
pd.Series([1, None, 4, 10, 8]).interpolate()
#四分位数法过滤
upper_q=df["D"].quantile(0.75)
lower_q=df["D"].quantile(0.25)
q_int=upper_q-lower_q
df[df['D']<upper_q*q_int][df['D']>lower_q*q_int]
#规定数据必须是f开头的
df[[True if item.startswith("f") else False for item in list(df["F"].values)]]

特征预处理

标注(label):我们知道机器学习分为有监督学习和无监督学习。无监督学习的效果是不可控的,常常是被用来做探索性的实验。而在实际产品应用中,通常使用的是有监督学习。有监督的机器学习就需要有标注的数据来作为先验经验。

1. 分类标注:分类标注,就是我们常见的打标签。一般是从既定的标签中选择数据对应的标签,是封闭集合。如下图,一张图就可以有很多分类 / 标签:成人、女、黄种人、长发等。对于文字,可以标注主语、谓语、宾语,名词动词等。

适用:文本、图像、语音、视频

应用:脸龄识别,情绪识别,性别识别

2. 标框标注:机器视觉中的标框标注,很容易理解,就是框选要检测的对象。如人脸识别,首先要先把人脸的位置确定下来。行人识别,如下图。

适用:图像

应用:人脸识别,物品识别

3. 区域标注:相比于标框标注,区域标注要求更加精确。边缘可以是柔性的。如自动驾驶中的道路识别。

应用:自动驾驶

4. 描点标注:一些对于特征要求细致的应用中常常需要描点标注。人脸识别、骨骼识别等。

应用:人脸识别、骨骼识别

5. 其他标注:标注的类型除了上面几种常见,还有很多个性化的。根据不同的需求则需要不同的标注。如自动摘要,就需要标注文章的主要观点,这时候的标注严格上就不属于上面的任何一种了。(或则你把它归为分类也是可以的,只是标注主要观点就没有这么客观的标准,如果是标注苹果估计大多数人标注的结果都差不多。)

一、特征选择:剔除与标注不相关或冗余的特征

思路:过滤思想、包裹思想、嵌入思想。

过滤思想:利用该表

#例:特征选择
import pandas as pd
import numpy as np
import scipy.stats as ss
from sklearn.feature_selection import SelectKBest,RFE,SelectFromModel
from sklearn.svm import SVR
from sklearn.tree import DecisionTreeRegressor

def main():
    df=pd.DataFrame({"A":ss.norm.rvs(size=10),\
                     "B":ss.norm.rvs(size=10),\
                     "C":ss.norm.rvs(size=10),\
                     "D":np.random.randint(low=0,high=2,size=10)})
    # 特征
    X=df.loc[:,["A","B","C"]]
    # 标注
    Y=df.loc[:,"D"]
    print("X",X)
    print("Y",Y)
    #过滤思想,选择两个得分较高的
    skb=SelectKBest(k=2,score_func=<function f_classif>)
    skb.fit(X.values,Y.values)
    print(skb.transform(X.values))
    #包裹思想,选择两个特种,每迭代一次,去掉一个特种
    rfe=RFE(estimator=SVR(kernel="linear"),n_features_to_select=2,step=1)
    print(rfe.fit_transform(X,Y))
    #嵌入思想,重要因子低于0。1去掉
    sfm=SelectFromModel(estimator=DecisionTreeRegressor(),threshold=0.1)
    print(sfm.fit_transform(X,Y))
if __name__=="__main__":
    main()

下面参考https://blog.csdn.net/a1368783069/article/details/52048349整理的内容:

1, 去掉取值变化小的特征(Removing features with low variance)

这应该是最简单的特征选择方法了:假设某特征的特征值只有0和1,并且在所有输入样本中,95%的实例的该特征取值都是1,那就可以认为这个特征作用不大。如果100%都是1,那这个特征就没意义了。当特征值都是离散型变量的时候这种方法才能用,如果是连续型变量,就需要将连续变量离散化之后才能用,而且实际当中,一般不太会有95%以上都取某个值的特征存在,所以这种方法虽然简单但是不太好用。可以把它作为特征选择的预处理,先去掉那些取值变化小的特征,然后再从接下来提到的的特征选择方法中选择合适的进行进一步的特征选择。

import pandas as pd
import numpy as np
import scipy.stats as ss
from sklearn.feature_selection import SelectKBest,RFE,SelectFromModel
from sklearn.svm import SVR
from sklearn.tree import DecisionTreeRegressor

from sklearn.feature_selection import VarianceThreshold
X = [[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1, 1]]
sel = VarianceThreshold(threshold=(.8 * (1 - .8)))
sel.fit_transform(X)

2, 单变量特征选择(Univariate feature selection)

基于单变量统计测试。

单变量特征选择能够对每一个特征进行测试,衡量该特征和响应变量之间的关系,根据得分扔掉不好的特征。对于回归和分类问题可以采用卡方检验等方式对特征进行测试。 
方法简单,易于运行,易于理解,通常对于理解数据有较好的效果(但对特征优化、提高泛化能力来说不一定有效);这种方法有许多改进的版本、变种。
 

import pandas as pd
import numpy as np
import scipy.stats as ss
import sklearn
#选择前k个分数较高的特征,去掉其他的特征。
sklearn.feature_selection.SelectKBest(score_func=<function f_classif>, k=10)
sklearn.feature_selection.SelectPercentile(score_func=<function f_classif>, percentile=10)
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
iris = load_iris()
X, y = iris.data, iris.target
X.shape
#f_regression(单因素线性回归试验)用作回归
#chi2卡方检验,f_classif(方差分析的F值)等用作分类
X_new = SelectKBest(chi2, k=2).fit_transform(X, y)
X_new.shape
#选择一定百分比的最高的评分的特征。
sklearn.feature_selection.SelectFpr(score_func=<function f_classif>, alpha=0.05)
#根据配置的参选搜索
sklearn.feature_selection.GenericUnivariateSelect(score_func=<function f_classif>, mode='percentile', param=1e-05)

3,递归特征消除Recursive feature elimination (RFE)

递归特征消除的主要思想是反复的构建模型(如SVM或者回归模型)然后选出最好的(或者最差的)的特征(可以根据系数来选),把选出来的特征选择出来,然后在剩余的特征上重复这个过程,直到所有特征都遍历了。这个过程中特征被消除的次序就是特征的排序。因此,这是一种寻找最优特征子集的贪心算法。 
RFE的稳定性很大程度上取决于在迭代的时候底层用哪种模型。例如,假如RFE采用的普通的回归,没有经过正则化的回归是不稳定的,那么RFE就是不稳定的;假如采用的是Ridge,而用Ridge正则化的回归是稳定的,那么RFE就是稳定的。
 

#例:特征选择
import pandas as pd
import numpy as np
import scipy.stats as ss
import sklearn
#class sklearn.feature_selection.RFECV(estimator, step=1, cv=None, scoring=None, estimator_params=None, verbose=0)


from sklearn.svm import SVC
from sklearn.datasets import load_digits
from sklearn.feature_selection import RFE
import matplotlib.pyplot as plt

# Load the digits dataset
digits = load_digits()
X = digits.images.reshape((len(digits.images), -1))
y = digits.target

# Create the RFE object and rank each pixel
svc = SVC(kernel="linear", C=1)
rfe = RFE(estimator=svc, n_features_to_select=1, step=1)
rfe.fit(X, y)
ranking = rfe.ranking_.reshape(digits.images[0].shape)

# Plot pixel ranking
plt.matshow(ranking)
plt.colorbar()
plt.title("Ranking of pixels with RFE")
plt.show()

4, Feature selection using SelectFromModel

SelectFromModel 是一个 meta-transformer,可以和在训练完后有一个coef_ 或者 feature_importances_ 属性的评估器(机器学习算法)一起使用。 
如果相应的coef_ 或者feature_importances_ 的值小于设置的阀值参数,这些特征可以视为不重要或者删除。除了指定阀值参数外,也可以通过设置一个字符串参数,使用内置的启发式搜索找到夜歌阀值。可以使用的字符串参数包括:“mean”, “median” 以及这两的浮点乘积,例如“0.1*mean”.
 

import matplotlib.pyplot as plt
import numpy as np

from sklearn.datasets import load_boston
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LassoCV

# Load the boston dataset.
boston = load_boston()
X, y = boston['data'], boston['target']

# We use the base estimator LassoCV since the L1 norm promotes sparsity of features.
clf = LassoCV()

# Set a minimum threshold of 0.25
sfm = SelectFromModel(clf, threshold=0.25)
sfm.fit(X, y)
n_features = sfm.transform(X).shape[1]

# Reset the threshold till the number of features equals two.
# Note that the attribute can be set directly instead of repeatedly
# fitting the metatransformer.
while n_features > 2:
    sfm.threshold += 0.1
    X_transform = sfm.transform(X)
    n_features = X_transform.shape[1]

# Plot the selected two features from X.
plt.title(
    "Features selected from Boston using SelectFromModel with "
    "threshold %0.3f." % sfm.threshold)
feature1 = X_transform[:, 0]
feature2 = X_transform[:, 1] 
plt.plot(feature1, feature2, 'r.')
plt.xlabel("Feature number 1")
plt.ylabel("Feature number 2")
plt.ylim([np.min(feature2), np.max(feature2)])
plt.show()

二、特征变换:对指化、离散化、数据平滑、归一化、数值化、正规化

(将数据间的差距变大了)

(将数据间差距变小了)

离散化(分箱):
深度:数的个数
宽度:数的区间

#数据分箱
import pandas as pd

lst = [6, 8, 10, 15, 16, 24, 25, 40, 67]
#等深分箱
x = pd.qcut(lst,q=3,labels=["low","medium","high"])
print(x)

#等宽分箱
x = pd.cut(lst,bins=3,labels=["low","medium","high"])
print(x)

#标准化
import numpy as np
from sklearn.preprocessing import MinMaxScaler,StandardScaler

print(MinMaxScaler().fit_transform(np.array([1, 4, 10, 15, 21]).reshape(-1, 1)))
print(StandardScaler().fit_transform(np.array([1, 1, 1, 1, 0, 0, 0, 0]).reshape(-1, 1)))
print(StandardScaler().fit_transform(np.array([1, 0, 0, 0, 0, 0, 0, 0]).reshape(-1, 1)))

数据的种类:

定类:数值化-独热

定序:数值化-标签化

import numpy as np

#标签化与独热编码
from sklearn.preprocessing import LabelEncoder,OneHotEncoder
print(LabelEncoder().fit_transform(np.array(["Down","Down","Up","Down","Up"]).reshape(-1,1)))
print(LabelEncoder().fit_transform(np.array(["Low","Medium","Low","High","Medium"]).reshape(-1,1)))

lb_encoder=LabelEncoder()
lb_trans_f=lb_encoder.fit_transform(np.array(["Red","Yellow","Blue","Green"]))
print(lb_trans_f)

oht_enoder=OneHotEncoder().fit(lb_trans_f.reshape(-1,1))
print(oht_enoder.transform(lb_encoder.transform(np.array(["Red","Blue"])).reshape(-1,1)).toarray())

定距:归一化

正规化(规范化):

L1正规化:

L2正规化(欧式正规化):

样例:

三种用法:

1、直接用在特征上
2、用在每个对象的各个特征的表示(特征矩阵的行)
3、模型的参数上(回归模型使用较多)

代码如下:

import numpy as np

# 规范化
from sklearn.preprocessing import Normalizer

print(Normalizer(norm="l1").fit_transform(np.array([[1, 1, 3, -1, 2]])))
print(Normalizer(norm="l2").fit_transform(np.array([[1, 1, 3, -1, 2]])))

 

特征降维

PCA(不标注)步骤:

LDA降维(有标注):线性判别式分析

X是特种、Y是标注(以二分类为例0、1)

根据行进行切分,一个标注都为0,另一个都为1

进行线性变化,成矩阵

从不同标注间距离来衡量:

同一标注内距离的衡量:

数学过程:

代码如下:

import numpy as np
# LDA降维
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
y = np.array([0, 0, 0, 1, 1, 1])
#降至一维
clf = LinearDiscriminantAnalysis(n_components=1).fit_transform(X,y)
print(clf)
#当作fisher_classifier分类器
clf = LinearDiscriminantAnalysis(n_components=1).fit(X, y)
print(clf.predict([[-0.8, -1]]))

特征衍生

常用的方法:

1.四则运算(加减乘除)

2.求导与高阶求导

3.人工归纳

例子:

1122是购买最多的,2商品出现月份看出可能是冬季用品,1122一定会买12号商品。

HR表的处理:

import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler,StandardScaler
from sklearn.preprocessing import LabelEncoder,OneHotEncoder
from sklearn.preprocessing import Normalizer
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.decomposition import PCA
from numpy import float64

def hr_preprocessing(sl=False,le=False,npr=False,amh=False,tsc=False,wa=False,pl5=False,dp=False,slr=False,lower_d=False,ld_n=1):
    f = open("/Users/ren/PycharmProjects/untitled7/data/HR.csv")
    df = pd.read_csv(f)
    # 清洗数据
    df = df.dropna(subset=["satisfaction_level", "last_evaluation"])
    df = df[df["satisfaction_level"] <= 1][df["salary"] != "nme"]
    #得到标注
    label = df["left"]
    #去除异常值,行去除
    df = df.drop("left", axis=1)
    #特征选择
    #特征处理
    scaler_lst=[sl,le,npr,amh,tsc,wa,pl5]
    column_lst=["satisfaction_level","last_evaluation","number_project",\
                "average_monthly_hours","time_spend_company","Work_accident",\
                "promotion_last_5years"]
    for i in range(len(scaler_lst)):
        if not scaler_lst[i]:
            df[column_lst[i]]=\
            MinMaxScaler().fit_transform(df[column_lst[i]].values.reshape(-1,1)).reshape(1,-1)[0]
        else:
            df[column_lst[i]]=\
            StandardScaler().fit_transform(df[column_lst[i]].values.reshape(-1,1)).reshape(1,-1)[0]



    scaler_lst=[slr,dp]
    column_lst=[ "salary","department"]
    for i in range(len(scaler_lst)):
        if not scaler_lst[i]:
            if column_lst[i]=="salary":
                df[column_lst[i]]=[map_salary(s) for s in df["salary"].values]
            else:
                df[column_lst[i]]=LabelEncoder().fit_transform(df[column_lst[i]])
            df[column_lst[i]] = MinMaxScaler().fit_transform(df[column_lst[i]].values.reshape(-1, 1)).reshape(1, -1)[0]
        else:
            df=pd.get_dummies(df,columns=[column_lst[i]])
    if lower_d:
        #PCA降维
        return PCA(n_components=ld_n).fit_transform(df.values),label


    return df,label
d=dict([("low",0),("medium",1),("high",2)])
def map_salary(s):
    return d.get(s,0)

def main():
    print(hr_preprocessing(sl=True,le=True,dp=True,lower_d=True,ld_n=3))

if __name__ == '__main__':
    main()

小结:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值