离散值处理 关于特征值离散化的相关内容下面直接进行举例,主要是标签处理、特征处理和OneHot。
import pandas as pd df = pd.DataFrame([ ['green' , 'M' , 10.1, 'class1' ], ['red' , 'L' , 13.5, 'class2' ], ['blue' , 'XL' , 15.3, 'class1' ]]) df.columns = ['color' , 'size' , 'prize' , 'class label' ] df
标签处理 通常我们会把字符型的标签转换成数值型的
class_mapping = {label:idx for idx,label in enumerate(set (df['class label' ]))} df['class label' ] = df['class label' ].map(class_mapping) df
特征处理 对于特征来说,我们一般可以做一个映射的字典
size_mapping = { 'XL' : 3, 'L' : 2, 'M' : 1} df['size' ] = df['size' ].map(size_mapping) df
我们还可以做这样的转换进行编码
color_mapping = { 'green' : (0,0,1), 'red' : (0,1,0), 'blue' : (1,0,0)} df['color' ] = df['color' ].map(color_mapping) df
对于数据,我们同样可以给它反变换回去
inv_color_mapping = {v: k for k, v in color_mapping.items()} inv_size_mapping = {v: k for k, v in size_mapping.items()} inv_class_mapping = {v: k for k, v in class_mapping.items()} df['color' ] = df['color' ].map(inv_color_mapping) df['size' ] = df['size' ].map(inv_size_mapping) df['class label' ] = df['class label' ].map(inv_class_mapping) df
scikit-learn 特征处理 scikit LabelEncoder from sklearn.preprocessing import LabelEncoder class_le = LabelEncoder() df['class label' ] = class_le.fit_transform(df['class label' ]) df
反变换回去可以用这个函数 inverse_transform
:
class_le.inverse_transform(df['class label' ])
scikit DictVectorizer 使用 DictVectorizer
将得到特征的字典
df.transpose().to_dict().values() feature = df.iloc[:, :-1] feature
对所有的数据都做了映射
from sklearn.feature_extraction import DictVectorizer dvec = DictVectorizer(sparse=False) X = dvec.fit_transform(feature.transpose().to_dict().values()) X
可以调用 get_feature_names
来返回新的列的名字,其中0和1就代表是不是这个属性.
pd.DataFrame(X, columns=dvec.get_feature_names())
scikit OneHotEncoder OneHotEncoder 必须使用整数作为输入,所以得先预处理一下
color_le = LabelEncoder()
df['color' ] = color_le.fit_transform(df['color' ]) df
from sklearn.preprocessing import OneHotEncoder ohe = OneHotEncoder(sparse=False) X = ohe.fit_transform(df[['color' ]].values) X
pandas get_dummies Pandas库中同样有类似的操作,使用get_dummies也可以得到相应的特征
import pandas as pd df = pd.DataFrame([ ['green' , 'M' , 10.1, 'class1' ], ['red' , 'L' , 13.5, 'class2' ], ['blue' , 'XL' , 15.3, 'class1' ]]) df.columns = ['color' , 'size' , 'prize' , 'class label' ] size_mapping = { 'XL' : 3, 'L' : 2, 'M' : 1} df['size' ] = df['size' ].map(size_mapping) class_mapping = {label:idx for idx,label in enumerate(set (df['class label' ]))} df['class label' ] = df['class label' ].map(class_mapping) df
对整个DF使用get_dummies
将会得到新的列:
pd.get_dummies(df)
标准化与归一化 标准化 同样我们都需要对原始数据进行处理,少不了的就是 standardization (或者叫做 Z-score normalization )
要求 均值 和标准差
转换公式如下:
这个意义是十分重大的,想象一下,我们经常通过梯度下降来进行优化求解,公式一般如下,如果特征之间的数值差异太大,那么更新的结果肯定也会产生较大的差异,这是我们所不希望的。在最开始的时候,我们认为特征之间的重要程度的是一样,并不想偏袒哪个特征,所以这部预处理工作必做!
参数更新:
归一化 另一种方法叫做 Min-Max scaling (或者叫做 "normalization"也就是我们常说的0-1归一化). 处理后的所有特征的值都会被压缩到 0到1区间上.这样做还可以抑制离群值对结果的影响.
归一化公式如下:
Standardizing 和 Normalizing的Scikit-learn实现 葡萄酒数据集由3个不同的类组成,每一行对应一个特定的葡萄酒样本。类标签(1、2、3)列在第一列中,列2-14对应13个不同的属性(特征):
from sklearn.datasets import load_wine wine = load_wine() df= pd.concat([pd.DataFrame(wine.target),pd.DataFrame(wine["data" ][:,:2],)],axis=1) df.columns = ['Class label' , 'Alcohol' , 'Malic acid' ]
在数据中,Alcohol和Malic acid 衡量的标准应该是不同的,特征之间数值差异较大
Standardization and Min-Max scaling from sklearn import preprocessing std_scale = preprocessing.StandardScaler().fit(df[['Alcohol' , 'Malic acid' ]]) df_std = std_scale.transform(df[['Alcohol' , 'Malic acid' ]]) minmax_scale = preprocessing.MinMaxScaler().fit(df[['Alcohol' , 'Malic acid' ]]) df_minmax = minmax_scale.transform(df[['Alcohol' , 'Malic acid' ]])print ('Mean after standardization:\nAlcohol={:.2f}, Malic acid={:.2f}' .format(df_std[:,0].mean(), df_std[:,1].mean()))print ('\nStandard deviation after standardization:\nAlcohol={:.2f}, Malic acid={:.2f}' .format(df_std[:,0].std(), df_std[:,1].std()))
print ('Min-value after min-max scaling:\nAlcohol={:.2f}, Malic acid={:.2f}' .format(df_minmax[:,0].min(), df_minmax[:,1].min()))print ('\nMax-value after min-max scaling:\nAlcohol={:.2f}, Malic acid={:.2f}' .format(df_minmax[:,0].max(), df_minmax[:,1].max()))
plot from matplotlib import pyplot as plt def plot(): plt.figure(figsize=(8,6)) plt.scatter(df['Alcohol' ], df['Malic acid' ], color='green' , label='input scale' , alpha=0.5) plt.scatter(df_std[:,0], df_std[:,1], color='red' , label='Standardized [$N (\mu=0, \; \sigma=1)$]' , alpha=0.3) plt.scatter(df_minmax[:,0], df_minmax[:,1], color='blue' , label='min-max scaled [min=0, max=1]' , alpha=0.3) plt.title('Alcohol and Malic Acid content of the wine dataset' ) plt.xlabel('Alcohol' ) plt.ylabel('Malic Acid' ) plt.legend(loc='upper left' ) plt.grid() plt.tight_layout() plot() plt.show()
我们将原始的和变换后都放到了同一个图上,观察下结果吧!接下来我们再看看数据是否被打乱了呢?
fig, ax = plt.subplots(3, figsize=(6,14))for a,d,l in zip(range(len(ax)), (df[['Alcohol' , 'Malic acid' ]].values, df_std, df_minmax), ('Input scale' , 'Standardized [$N (\mu=0, \; \sigma=1)$]' , 'min-max scaled [min=0, max=1]' ) ): for i,c in zip(range(1,4), ('red' , 'blue' , 'green' )): ax[a].scatter(d[df['Class label' ].values == i, 0], d[df['Class label' ].values == i, 1], alpha=0.5, color=c, label='Class %s' %i ) ax[a].set_title(l) ax[a].set_xlabel('Alcohol' ) ax[a].set_ylabel('Malic Acid' ) ax[a].legend(loc='upper left' ) ax[a].grid() plt.tight_layout() plt.show()
在机器学习中,如果我们对训练集做了上述处理,那么同样的对测试集也必须要经过相同的处理
std_scale = preprocessing.StandardScaler().fit(X_train) X_train = std_scale.transform(X_train) X_test = std_scale.transform(X_test)