- 标签处理
- 特征处理
- 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
:
class_le.inverse_transform(df['class label'])
scikit DictVectorizer
使用 DictVectorizer
将得到特征的字典
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就代表是不是这个属性.
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
将会得到新的列:
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个不同的属性(特征):
- Alcohol
- Malic acid
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)