本文目录导读:

我来详细介绍使用Scikit-learn进行编码分类的几种常见方法:
基础分类流程
# 导入必要的库
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
# 创建示例数据
data = {
'颜色': ['红', '蓝', '绿', '红', '蓝', '绿'],
'大小': ['大', '中', '小', '中', '大', '小'],
'价格': [100, 80, 60, 120, 90, 70],
'类别': ['A', 'B', 'C', 'A', 'B', 'C']
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)
标签编码 (Label Encoding)
# 标签编码 - 将分类变量转换为数字
from sklearn.preprocessing import LabelEncoder
# 创建编码器
label_encoder = LabelEncoder()
# 对颜色列进行编码
df['颜色_编码'] = label_encoder.fit_transform(df['颜色'])
print("颜色编码映射:", dict(zip(label_encoder.classes_, label_encoder.transform(label_encoder.classes_))))
# 对大小列进行编码
df['大小_编码'] = label_encoder.fit_transform(df['大小'])
print("大小编码映射:", dict(zip(label_encoder.classes_, label_encoder.transform(label_encoder.classes_))))
独热编码 (One-Hot Encoding)
# 方法1: 使用 pandas get_dummies
df_onehot = pd.get_dummies(df, columns=['颜色', '大小'], prefix=['颜色', '大小'])
print("独热编码结果:")
print(df_onehot)
# 方法2: 使用 sklearn OneHotEncoder
from sklearn.preprocessing import OneHotEncoder
import pandas as pd
# 准备数据
X = df[['颜色', '大小']].values.reshape(-1, 2)
# 创建和训练编码器
onehot_encoder = OneHotEncoder(sparse_output=False) # 返回密集矩阵
X_encoded = onehot_encoder.fit_transform(X)
print("\nOneHotEncoder 结果:")
print(X_encoded)
print("特征名称:", onehot_encoder.get_feature_names_out(['颜色', '大小']))
完整的分类流程示例
# 完整示例:使用随机森林进行分类
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score
# 1. 准备数据
def prepare_data():
# 创建更多数据
np.random.seed(42)
n_samples = 100
data = {
'颜色': np.random.choice(['红', '蓝', '绿'], n_samples),
'大小': np.random.choice(['大', '中', '小'], n_samples),
'价格': np.random.uniform(50, 200, n_samples),
'销量': np.random.choice(['高', '中', '低'], n_samples)
}
df = pd.DataFrame(data)
# 特征和目标
X = df[['颜色', '大小', '价格']]
y = df['销量']
return X, y
# 2. 创建预处理流程
def create_preprocessor():
# 数值特征
numeric_features = ['价格']
numeric_transformer = StandardScaler()
# 分类特征
categorical_features = ['颜色', '大小']
categorical_transformer = OneHotEncoder(sparse_output=False)
# 合并预处理
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
])
return preprocessor
# 3. 创建完整管道
def create_pipeline():
preprocessor = create_preprocessor()
pipeline = Pipeline([
('preprocessor', preprocessor),
('classifier', RandomForestClassifier(n_estimators=100, random_state=42))
])
return pipeline
# 4. 训练和评估
def train_and_evaluate():
# 准备数据
X, y = prepare_data()
# 编码目标变量
label_encoder = LabelEncoder()
y_encoded = label_encoder.fit_transform(y)
# 分割数据
X_train, X_test, y_train, y_test = train_test_split(
X, y_encoded, test_size=0.2, random_state=42
)
# 创建和训练模型
pipeline = create_pipeline()
pipeline.fit(X_train, y_train)
# 预测
y_pred = pipeline.predict(X_test)
# 评估
print("\n分类报告:")
print(classification_report(y_test, y_pred,
target_names=label_encoder.classes_))
# 混淆矩阵
print("混淆矩阵:")
print(confusion_matrix(y_test, y_pred))
# 交叉验证
cv_scores = cross_val_score(pipeline, X, y_encoded, cv=5)
print(f"\n交叉验证分数: {cv_scores.mean():.3f} (+/- {cv_scores.std() * 2:.3f})")
return pipeline, label_encoder
# 运行完整示例
pipeline, label_encoder = train_and_evaluate()
处理新数据进行预测
# 对新数据进行预测
def predict_new_data(pipeline, label_encoder):
new_data = pd.DataFrame({
'颜色': ['红', '蓝', '绿'],
'大小': ['中', '大', '小'],
'价格': [100, 150, 80]
})
print("\n新数据预测:")
predictions = pipeline.predict(new_data)
predicted_labels = label_encoder.inverse_transform(predictions)
for i, (_, row) in enumerate(new_data.iterrows()):
print(f"颜色:{row['颜色']}, 大小:{row['大小']}, "
f"价格:{row['价格']} -> 预测销量:{predicted_labels[i]}")
# 进行预测
predict_new_data(pipeline, label_encoder)
其他编码方法
# 二值化编码 (Binary Encoding)
from sklearn.preprocessing import Binarizer
# 创建二值化器
binarizer = Binarizer(threshold=80)
df['价格_二值化'] = binarizer.fit_transform(df[['价格']])
print("\n价格二值化结果 (阈值=80):")
print(df[['价格', '价格_二值化']])
# 序数编码 (Ordinal Encoding) - 适用于有序分类
from sklearn.preprocessing import OrdinalEncoder
# 指定顺序
size_order = [['小', '中', '大']] # 从小到大
ordinal_encoder = OrdinalEncoder(categories=size_order)
df['大小_序数'] = ordinal_encoder.fit_transform(df[['大小']])
print("\n大小序数编码:")
print(df[['大小', '大小_序数']])
处理文本数据的编码
# 文本特征提取
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
# 示例文本数据
texts = [
"这款手机很好用",
"价格很实惠",
"质量差,不推荐",
"性价比很高"
]
# 词袋模型
count_vectorizer = CountVectorizer()
X_bow = count_vectorizer.fit_transform(texts)
print("词袋模型特征:")
print(count_vectorizer.get_feature_names_out())
print(X_bow.toarray())
# TF-IDF
tfidf_vectorizer = TfidfVectorizer()
X_tfidf = tfidf_vectorizer.fit_transform(texts)
print("\nTF-IDF特征矩阵:")
print(X_tfidf.toarray())
完整示例代码
# 完整的端到端示例
def complete_classification_example():
"""
完整的分分类例子,包括数据预处理、编码、训练和评估
"""
# 1. 生成示例数据
np.random.seed(42)
n = 200
data = {
'城市': np.random.choice(['北京', '上海', '广州', '深圳'], n),
'产品类型': np.random.choice(['电子', '服装', '食品', '日用品'], n),
'客户等级': np.random.choice(['VIP', '普通', '新客户'], n),
'月消费': np.random.uniform(100, 5000, n),
'满意度': np.random.choice(['满意', '一般', '不满意'], n)
}
df = pd.DataFrame(data)
# 2. 特征和目标
X = df[['城市', '产品类型', '客户等级', '月消费']]
y = df['满意度']
# 3. 编码目标变量
le = LabelEncoder()
y_encoded = le.fit_transform(y)
# 4. 创建预处理和模型管道
numeric_features = ['月消费']
categorical_features = ['城市', '产品类型', '客户等级']
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), numeric_features),
('cat', OneHotEncoder(sparse_output=False), categorical_features)
])
pipeline = Pipeline([
('preprocessor', preprocessor),
('classifier', RandomForestClassifier(n_estimators=100, random_state=42))
])
# 5. 训练和评估
X_train, X_test, y_train, y_test = train_test_split(
X, y_encoded, test_size=0.2, random_state=42
)
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
# 6. 输出结果
print("="*50)
print("分类结果摘要")
print("="*50)
print(f"准确率: {accuracy_score(y_test, y_pred):.3f}")
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=le.classes_))
# 7. 特征重要性
if hasattr(pipeline.named_steps['classifier'], 'feature_importances_'):
feature_names = (numeric_features +
list(pipeline.named_steps['preprocessor']
.named_transformers_['cat']
.get_feature_names_out(categorical_features)))
importances = pipeline.named_steps['classifier'].feature_importances_
print("\n特征重要性:")
for name, imp in sorted(zip(feature_names, importances),
key=lambda x: x[1], reverse=True)[:5]:
print(f"{name}: {imp:.3f}")
# 运行完整示例
from sklearn.metrics import accuracy_score
complete_classification_example()
重要提示
-
选择编码方式的考虑因素:
- 序数数据:使用OrdinalEncoder或LabelEncoder
- 名义数据(无顺序):使用OneHotEncoder
- 高基数特征:考虑使用Target Encoding或Count Encoding
-
避免数据泄露:
- 在训练集上fit编码器,然后transform训练集和测试集
- 使用Pipeline可以自动处理这个问题
-
处理未知类别:
- 设置handle_unknown='ignore'在OneHotEncoder中
- 这样测试集中出现训练集未见的类别时不会报错
这些示例涵盖了Scikit-learn中主要的编码分类方法,可以根据具体需求选择合适的方式。