1、缩放特征(Feature Scaling)
特征预处理是一个重要的步骤,而特征缩放(Feature Scaling)是其中的一个关键环节。特征缩放通常用于标准化数据集中各个特征的范围,使它们在相似的尺度上。这一步骤对于许多机器学习算法特别重要,尤其是那些基于距离的算法(如 K-近邻)和梯度下降法(如线性回归、逻辑回归、神经网络)。
1)最小-最大缩放 (Min-Max Scaling)
最小-最大缩放将所有特征缩放到一个给定的范围内,通常是 0
到 1
。公式如下:
import numpy as np
def min_max_scaling(X):
"""
最小-最大缩放
Args:
X: 特征矩阵
Returns:
缩放后的特征矩阵
"""
# 计算每个特征的最小值和最大值
x_min = np.min(X, axis=0)
x_max = np.max(X, axis=0)
# 缩放特征
X_scaled = (X - x_min) / (x_max - x_min)
return X_scaled
# 示例
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
X_scaled = min_max_scaling(X)
print(X_scaled)
# 输出:
# [[0. 0. 0.]
# [0.5 0.5 0.5]
# [1. 1. 1.]]
使用 MinMaxScaler
类来实现:
from sklearn.preprocessing import MinMaxScaler
import numpy as np
# 示例数据
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float64)
# 创建缩放器并应用
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(data)
print(scaled_data)
2)标准化 (Standardization)
标准化将特征缩放,使其具有零均值和单位方差。公式如下:
import numpy as np
def standardize(X):
"""
对数据进行标准化
Args:
X: 输入数据,numpy 数组
Returns:
标准化后的数据
"""
# 计算均值和标准差
mu = np.mean(X, axis=0)
sigma = np.std(X, axis=0)
# 标准化
Z = (X - mu) / sigma
return Z
# 示例
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
Z = standardize(X)
print(Z)
使用 StandardScaler
类:
from sklearn.preprocessing import StandardScaler
import numpy as np
# 示例数据
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float64)
# 创建缩放器并应用
scaler = StandardScaler()
scaled_data = scaler.fit_transform(data)
print(scaled_data)
3)范数缩放 (Normalization)
范数缩放通常是将每个样本缩放到单位范数(每个样本的向量长度为1
)。可以使用 Normalizer 类来实现:
from sklearn.preprocessing import Normalizer
# 示例数据
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float64)
# 创建缩放器并应用
scaler = Normalizer()
scaled_data = scaler.fit_transform(data)
print(scaled_data)
2、缺失值处理
特征预处理其中一个关键的环节是处理缺失值。缺失值会影响模型的性能,因此需要采取适当的策略来处理它们。Python 中有多种方法可以处理缺失值,主要使用 Pandas 和 Scikit-learn 库。
如果数据集不是很大,并且缺失值不是太多,可以考虑直接删除含有缺失值的行或列。也可以用一些具体的值来填充缺失值,例如用平均值、中位数或众数等。Scikit-learn 提供了 SimpleImputer
类,这是处理缺失值的另一种常用方法。在某些情况下,可能需要使用更复杂的方法来填充缺失值。
import pandas as pd
from sklearn.impute import SimpleImputer
import numpy as np
# 假设 df 是一个包含缺失值的 DataFrame
# 示例数据
data = {
'Feature1': [1, np.nan, 3, 4, 5],
'Feature2': [6, 7, np.nan, 9, 10],
'Feature3': [11, 12, 13, np.nan, 15]
}
df = pd.DataFrame(data)
# 删除含有缺失值的行
df_dropped_rows = df.dropna()
# 删除含有缺失值的列
df_dropped_columns = df.dropna(axis=1)
# 用平均值填充
df_filled_mean = df.fillna(df.mean())
# 用中位数填充
df_filled_median = df.fillna(df.median())
# 用众数填充
df_filled_mode = df.fillna(df.mode().iloc[0])
# 使用 SimpleImputer 用平均值填充
imputer_mean = SimpleImputer(missing_values=np.nan, strategy='mean')
df_imputed_mean = pd.DataFrame(imputer_mean.fit_transform(df), columns=df.columns)
# 使用 SimpleImputer 用中位数填充
imputer_median = SimpleImputer(missing_values=np.nan, strategy='median')
df_imputed_median = pd.DataFrame(imputer_median.fit_transform(df), columns=df.columns)
# 使用 SimpleImputer 用众数填充
imputer_mode = SimpleImputer(missing_values=np.nan, strategy='most_frequent')
df_imputed_mode = pd.DataFrame(imputer_mode.fit_transform(df), columns=df.columns)
# 输出各种方法处理后的结果
print(df_dropped_rows, df_dropped_columns, df_filled_mean, df_filled_median, df_filled_mode, df_imputed_mean, df_imputed_median, df_imputed_mode)
3、编码分类特征
当数据集包含分类(非数值)特征时,通常需要对这些特征进行编码,以便机器学习算法能够处理它们。分类特征的编码主要有两种方式:标签编码(Label Encoding)和独热编码(One-Hot Encoding)。
1)标签编码
标签编码将每个类别映射到一个整数。这种方法的一个问题是,它可能导致算法错误地假设数据中的数字有序。
from sklearn.preprocessing import LabelEncoder
# 假设有一个分类特征
categories = ['red', 'blue', 'green']
# 创建 LabelEncoder 对象
label_encoder = LabelEncoder()
# 应用标签编码
encoded_labels = label_encoder.fit_transform(categories)
print(encoded_labels)
2)独热编码
独热编码创建了一个二进制列,用于每个类别。对于类别的每个值,独热编码都会创建一个新的列(特征),其中只有一个是 1,其他都是 0。
使用scikit-learn:
from sklearn.preprocessing import OneHotEncoder
import numpy as np
# 示例数据
categories = np.array([['Red'], ['Green'], ['Blue'], ['Green'], ['Red']])
# 创建 OneHotEncoder 实例
encoder = OneHotEncoder()
# 训练编码器并转换数据
one_hot_encoded = encoder.fit_transform(categories)
print(one_hot_encoded)
使用 pandas:
import pandas as pd
# 示例数据
df = pd.DataFrame({'Color': ['Red', 'Green', 'Blue', 'Green', 'Red']})
# 使用 pandas 的 get_dummies 方法进行独热编码
one_hot_encoded = pd.get_dummies(df)
print(one_hot_encoded)
4、生成多项式特征
生成多项式特征是一种常见的预处理方法,特别是在使用线性模型时。多项式特征可以帮助模型捕捉数据中的非线性关系。特别适用于提高线性模型的复杂度,使其能够学习更复杂的数据模式。
from sklearn.preprocessing import PolynomialFeatures
import numpy as np
# 示例数据
X = np.array([[2], [3], [4]])
# 创建一个度为 2 的 PolynomialFeatures 转换器
poly = PolynomialFeatures(degree=2)
# 转换数据
X_poly = poly.fit_transform(X)
# 输出结果
print(X_poly)
5、使用 Python 进行特征预处理
scikit-learn 库提供了大量的工具来进行特征预处理。使用鸢尾花数据集,并人为添加了一些分类特征和缺失值。然后定义了一个预处理管道,其中包括对数值特征的标准化和对分类特征的独热编码。使用随机森林分类器构建了一个模型,并在训练数据上训练它,然后在测试数据上评估其性能。代码如下,
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# 加载鸢尾花数据集
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target
# 假设我们添加一些包含缺失值和分类特征的数据
# 添加分类特征
X['flower_category'] = np.random.choice(['Category 1', 'Category 2', 'Category 3'], size=len(X))
# 人为添加一些缺失值
X.iloc[::10, 1] = np.nan
# 分割数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 定义数值特征和分类特征
numeric_features = iris.feature_names
categorical_features = ['flower_category']
# 创建预处理步骤
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())])
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='constant', fill_value='missing')),
('onehot', OneHotEncoder(handle_unknown='ignore'))])
# 组合预处理步骤
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)])
# 创建完整的训练管道
pipeline = Pipeline(steps=[('preprocessor', preprocessor),
('classifier', RandomForestClassifier(random_state=42))])
# 训练模型
pipeline.fit(X_train, y_train)
# 进行预测
y_pred = pipeline.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"Model accuracy: {accuracy:.4f}")