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}")