本文目录导读:

我来为你详细介绍如何使用Scikit-learn进行互信息(Mutual Information)特征选择。
什么是互信息?
互信息用于衡量两个变量之间的依赖性,可以捕捉线性和非线性关系,值越大表示特征与目标变量的关联越强。
基础案例
示例1:分类问题的互信息选择
import numpy as np
import pandas as pd
from sklearn.feature_selection import mutual_info_classif, SelectKBest
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
# 加载数据
iris = load_iris()
X, y = iris.data, iris.target
feature_names = iris.feature_names
# 计算互信息分数
mi_scores = mutual_info_classif(X, y, random_state=42)
# 创建DataFrame直观显示
mi_df = pd.DataFrame({
'feature': feature_names,
'mi_score': mi_scores
})
mi_df = mi_df.sort_values('mi_score', ascending=False)
print("互信息分数(降序):")
print(mi_df)
print("\n" + "="*50)
# 选择Top-K特征
selector = SelectKBest(score_func=mutual_info_classif, k=2)
X_selected = selector.fit_transform(X, y)
# 显示选中的特征
selected_indices = selector.get_support(indices=True)
print(f"\n选中的特征索引:{selected_indices}")
print(f"选中的特征名称:{[feature_names[i] for i in selected_indices]}")
print(f"原始特征维度:{X.shape}")
print(f"选择后特征维度:{X_selected.shape}")
# 可视化互信息分数
plt.figure(figsize=(10, 6))
plt.bar(mi_df['feature'], mi_df['mi_score'])'互信息特征重要性', fontsize=14)
plt.xlabel('特征', fontsize=12)
plt.ylabel('互信息分数', fontsize=12)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
示例2:回归问题的互信息选择
from sklearn.feature_selection import mutual_info_regression
from sklearn.datasets import load_diabetes
# 加载糖尿病数据集(回归问题)
diabetes = load_diabetes()
X, y = diabetes.data, diabetes.target
feature_names = diabetes.feature_names
# 计算互信息分数(回归用mutual_info_regression)
mi_scores_reg = mutual_info_regression(X, y, random_state=42)
# 可视化
mi_df_reg = pd.DataFrame({
'feature': feature_names,
'mi_score': mi_scores_reg
}).sort_values('mi_score', ascending=True)
plt.figure(figsize=(10, 8))
plt.barh(mi_df_reg['feature'], mi_df_reg['mi_score'])
plt.xlabel('互信息分数')'回归问题 - 互信息特征重要性')
plt.tight_layout()
plt.show()
实际应用案例
示例3:完整的特征选择流程
import warnings
warnings.filterwarnings('ignore')
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_classification
# 生成样本数据
X, y = make_classification(n_samples=1000, n_features=20, n_informative=5,
n_redundant=5, n_repeated=5, random_state=42)
# 分割数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
print(f"原始特征数量:{X.shape[1]}")
# 1. 计算互信息
mi_scores = mutual_info_classif(X_train, y_train, random_state=42)
# 2. 设置阈值选择特征
threshold = np.percentile(mi_scores, 50) # 选择分数前50%的特征
selected_features = np.where(mi_scores > threshold)[0]
print(f"选择的特征数量:{len(selected_features)}")
print(f"互信息分数范围:{mi_scores.min():.4f} - {mi_scores.max():.4f}")
print(f"选择阈值:{threshold:.4f}")
# 3. 特征选择
X_train_selected = X_train[:, selected_features]
X_test_selected = X_test[:, selected_features]
# 4. 训练和评估
rf_clf = RandomForestClassifier(random_state=42)
rf_clf.fit(X_train_selected, y_train)
y_pred = rf_clf.predict(X_test_selected)
accuracy_full = accuracy_score(y_test, y_pred)
# 与全部特征的对比
rf_clf_full = RandomForestClassifier(random_state=42)
rf_clf_full.fit(X_train, y_train)
y_pred_full = rf_clf_full.predict(X_test)
accuracy_selected = accuracy_score(y_test, y_pred_full)
print(f"\n全部特征准确率:{accuracy_full:.4f}")
print(f"选择特征准确率:{accuracy_selected:.4f}")
示例4:自动确定最佳特征数量
from sklearn.feature_selection import SelectPercentile
# 使用SelectPercentile选择百分比特征
selector_percent = SelectPercentile(score_func=mutual_info_classif, percentile=30)
X_percent = selector_percent.fit_transform(X_train, y_train)
print(f"保留30%的特征后维度:{X_percent.shape}")
# 通过交叉验证选择最佳k值
from sklearn.model_selection import cross_val_score
def find_best_k(X, y, k_range=[5, 10, 15, 20]):
"""通过交叉验证找到最佳的K值"""
best_score = 0
best_k = k_range[0]
for k in k_range:
selector = SelectKBest(score_func=mutual_info_classif, k=k)
X_selected = selector.fit_transform(X, y)
# 交叉验证
scores = cross_val_score(RandomForestClassifier(),
X_selected, y, cv=3)
mean_score = scores.mean()
print(f"K={k}: CV准确率={mean_score:.4f} (±{scores.std():.4f})")
if mean_score > best_score:
best_score = mean_score
best_k = k
return best_k, best_score
print("\n寻找最佳特征数量:")
best_k, best_score = find_best_k(X_train, y_train)
print(f"\n最佳特征数量:{best_k},准确率:{best_score:.4f}")
实际数据应用案例
示例5:处理真实世界数据
import seaborn as sns
from sklearn.impute import SimpleImputer
# 加载Titanic数据集
titanic = sns.load_dataset('titanic')
print("原始数据形状:", titanic.shape)
# 数据预处理
# 选择数值特征
numeric_features = ['pclass', 'age', 'sibsp', 'parch', 'fare']
categorical_features = ['sex', 'embarked', 'class', 'who', 'adult_male', 'deck', 'embark_town']
# 处理目标变量
y_titanic = titanic['survived']
# 处理数值特征
X_numeric = titanic[numeric_features].copy()
# 处理缺失值
imputer = SimpleImputer(strategy='median')
X_numeric_imputed = imputer.fit_transform(X_numeric)
# 处理类别特征
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
X_categorical = pd.DataFrame()
for col in categorical_features:
if col in titanic.columns:
# 填充缺失值
temp = titanic[col].fillna('Unknown')
X_categorical[col] = le.fit_transform(temp)
# 合并特征
X_titanic = np.hstack([X_numeric_imputed, X_categorical])
print(f"处理后特征数量:{X_titanic.shape[1]}")
# 计算互信息
mi_scores_titanic = mutual_info_classif(X_titanic, y_titanic, random_state=42)
# 特征重要性排序
feature_names_titanic = numeric_features + [col for col in categorical_features if col in titanic.columns]
mi_titanic_df = pd.DataFrame({
'feature': feature_names_titanic,
'mi_score': mi_scores_titanic
}).sort_values('mi_score', ascending=False)
print("\n特征重要性排名(前10):")
print(mi_titanic_df.head(10))
# 选择Top-5特征
selector_titanic = SelectKBest(score_func=mutual_info_classif, k=5)
X_titanic_selected = selector_titanic.fit_transform(X_titanic, y_titanic)
selected_features_titanic = np.array(feature_names_titanic)[selector_titanic.get_support()]
print(f"\n选择的Top-5特征:{selected_features_titanic}")
重要参数说明
# mutual_info_classif的主要参数
mi_scores = mutual_info_classif(
X, # 特征矩阵
y, # 目标变量
discrete_features='auto', # 是否将特征视为离散特征
n_neighbors=3, # 用于估计的邻居数
copy=True, # 是否复制数据
random_state=42 # 随机种子
)
# SelectKBest的主要参数
selector = SelectKBest(
score_func=mutual_info_classif, # 评分函数
k=10, # 选择特征数量
)
注意事项
# 1. 数据标准化不影响互信息
# 互信息不依赖数据分布,无需标准化
# 2. 处理离散特征
# 对于离散特征,设置discrete_features参数
mi_scores_mixed = mutual_info_classif(
X, y,
discrete_features=[True, True, False, False], # 指定哪些特征是离散的
random_state=42
)
# 3. 互信息值范围
# 理论范围:[0, +∞)
# 实际中通常较小,需要进行归一化处理
mi_normalized = mi_scores / mi_scores.max() # 归一化到[0,1]
print(f"归一化互信息分数:{mi_normalized[:5]}")
互信息特征选择的优势:
- 可以捕捉非线性关系
- 不依赖数据缩放
- 可处理多种数据类型
- 理论解释性强
适用场景:
- 特征数量多,需要降维
- 特征与目标关系复杂
- 需要了解特征重要性
通过以上案例,你可以根据实际问题选择合适的互信息特征选择方法。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播