机器学习特征数据预处理

2022-08-18 10:34:10 浏览数 (2)

  • 标签处理
  • 特征处理
  • scikit-learn 特征处理
    • scikit LabelEncoder
    • scikit DictVectorizer
    • scikit OneHotEncoder
    • pandas get_dummies
  • 标准化
  • 归一化
  • Standardization and Min-Max scaling
  • plot

离散值处理

关于特征值离散化的相关内容下面直接进行举例,主要是标签处理、特征处理和OneHot。

代码语言:javascript复制
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

标签处理

通常我们会把字符型的标签转换成数值型的

代码语言:javascript复制
class_mapping = {label:idx for idx,label in enumerate(set(df['class label']))}

df['class label'] = df['class label'].map(class_mapping)
df

特征处理

对于特征来说,我们一般可以做一个映射的字典

代码语言:javascript复制
size_mapping = {
           'XL': 3,
           'L': 2,
           'M': 1}

df['size'] = df['size'].map(size_mapping)
df

我们还可以做这样的转换进行编码

代码语言:javascript复制
color_mapping = {
           'green': (0,0,1),
           'red': (0,1,0),
           'blue': (1,0,0)}

df['color'] = df['color'].map(color_mapping)
df

对于数据,我们同样可以给它反变换回去

代码语言:javascript复制
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

代码语言:javascript复制
from sklearn.preprocessing import LabelEncoder

class_le = LabelEncoder()
df['class label'] = class_le.fit_transform(df['class label'])
df

反变换回去可以用这个函数 inverse_transform :

代码语言:javascript复制
class_le.inverse_transform(df['class label'])

scikit DictVectorizer

使用 DictVectorizer将得到特征的字典

代码语言:javascript复制
df.transpose().to_dict().values()
feature = df.iloc[:, :-1]
feature

对所有的数据都做了映射

代码语言:javascript复制
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就代表是不是这个属性.

代码语言:javascript复制
pd.DataFrame(X, columns=dvec.get_feature_names())

scikit OneHotEncoder

OneHotEncoder 必须使用整数作为输入,所以得先预处理一下

代码语言:javascript复制
color_le = LabelEncoder()
df['color'] = color_le.fit_transform(df['color'])

df
代码语言:javascript复制
from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder(sparse=False)

X = ohe.fit_transform(df[['color']].values)
X

pandas get_dummies

Pandas库中同样有类似的操作,使用get_dummies也可以得到相应的特征

代码语言:javascript复制
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 将会得到新的列:

代码语言:javascript复制
pd.get_dummies(df)

标准化与归一化

标准化

同样我们都需要对原始数据进行处理,少不了的就是 standardization (或者叫做 Z-score normalization)

要求 均值

mu = 0

和标准差

sigma = 1

转换公式如下:

z = frac{x - mu}{sigma}

这个意义是十分重大的,想象一下,我们经常通过梯度下降来进行优化求解,公式一般如下,如果特征之间的数值差异太大,那么更新的结果肯定也会产生较大的差异,这是我们所不希望的。在最开始的时候,我们认为特征之间的重要程度的是一样,并不想偏袒哪个特征,所以这部预处理工作必做!

Delta w_j = - eta frac{partial J}{partial w_j} = eta sum_i (t^{(i)} - o^{(i)})x^{(i)}_{j},

参数更新:

w_j := w_j Delta w_j,

归一化

另一种方法叫做 Min-Max scaling (或者叫做 "normalization"也就是我们常说的0-1归一化). 处理后的所有特征的值都会被压缩到 0到1区间上.这样做还可以抑制离群值对结果的影响. 归一化公式如下:

X_{norm} = frac{X - X_{min}}{X_{max}-X_{min}}

Standardizing 和 Normalizing的Scikit-learn实现

葡萄酒数据集由3个不同的类组成,每一行对应一个特定的葡萄酒样本。类标签(1、2、3)列在第一列中,列2-14对应13个不同的属性(特征):

  1. Alcohol
  2. Malic acid
代码语言:javascript复制
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

代码语言:javascript复制
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()))
代码语言:javascript复制
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

代码语言:javascript复制
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()

我们将原始的和变换后都放到了同一个图上,观察下结果吧!接下来我们再看看数据是否被打乱了呢?

代码语言:javascript复制
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()

在机器学习中,如果我们对训练集做了上述处理,那么同样的对测试集也必须要经过相同的处理

代码语言:javascript复制
std_scale = preprocessing.StandardScaler().fit(X_train)
X_train = std_scale.transform(X_train)
X_test = std_scale.transform(X_test)

0 人点赞