香人 發表於 2025-6-3 10:28:00

机器学习中的"食材挑选术":特征选择方法

<p>想象你要做一道美食,面对琳琅满目的食材,优秀的厨师不会把所有原料都扔进锅里,而是会选择最适合的几种。</p>
<p>在机器学习中,<strong>特征选择</strong>就是这个挑选过程,从原始数据中选择对预测目标最有用的特征(列),就像挑选优质食材一样重要。</p>
<h1 id="1-什么是特征选择">1. 什么是特征选择?</h1>
<p><strong>特征选择</strong>是机器学习中一个至关重要的步骤,它从原始数据的众多特征中挑选出对模型最有价值的子集。</p>
<p>简单来说,就是从一堆可能影响结果的因素中,找出那些真正重要的因素,把不重要的、重复的或者有干扰的特征去掉。</p>
<p>为什么要做<strong>特征选择</strong>呢?主要有以下几个原因:</p>
<ul>
<li><strong>提高模型性能</strong>:少而精的特征能帮助模型更专注于重要的信息,避免被无关特征干扰,从而提高准确性。</li>
<li><strong>加快训练速度</strong>:特征少了,模型需要处理的数据量就小了,训练时间自然也就缩短了。</li>
<li><strong>降低过拟合风险</strong>:过多的特征可能让模型记住噪声,而不是学习到真正的规律。特征选择能帮助模型更好地泛化。</li>
<li><strong>提升可解释性</strong>:特征少了,模型的决策过程更容易理解,这对很多实际应用场景非常重要。</li>
</ul>
<h1 id="2-三大特征选择方法">2. 三大特征选择方法</h1>
<p>根据<strong>特征选择</strong>与<strong>模型训练过程</strong>的关系,主要可以分为以下三类方法:</p>
<h2 id="21-过滤式先筛后用">2.1. 过滤式:先"筛"后"用"</h2>
<p><strong>过滤式</strong>方法就像用筛子筛沙子一样,先根据特征本身的统计特性对特征进行评估和筛选,然后再把选出来的特征交给模型使用。</p>
<p>这个过程完全独立于机器学习模型。</p>
<p>常见的<strong>过滤式</strong>方法包括:</p>
<ul>
<li><strong>方差阈值</strong>:去掉那些几乎不变的特征(方差低于某个阈值)</li>
<li><strong>卡方检验</strong>:评估分类问题中特征与目标变量的独立性</li>
<li><strong>相关系数</strong>:计算特征与目标变量之间的相关性</li>
</ul>
<p>下面的代码演示如何使用<strong>过滤式</strong>方法来进行特征选择,使用<strong>卡方检验</strong>(<code>SelectBest</code>):</p>
<pre><code class="language-python">from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.model_selection import train_test_split

# 加载数据集
iris = load_iris()
X, y = iris.data, iris.target

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 创建过滤式选择器,选择2个最佳特征
selector = SelectKBest(score_func=f_classif, k=2)
X_train_selected = selector.fit_transform(X_train, y_train)
X_test_selected = selector.transform(X_test)

# 查看选中的特征
selected_features = selector.get_support(indices=True)
print(f"选中的特征索引: {selected_features}")
print(f"特征得分: {selector.scores_}")

# 输出特征选择后的数据维度
print(f"原始训练集特征数: {X_train.shape}")
print(f"选择后训练集特征数: {X_train_selected.shape}")

## 输出结果:
'''
选中的特征索引:
特征得分: [ 74.7572012   33.41979913 713.45534904 526.54162416]
原始训练集特征数: 4
选择后训练集特征数: 2
'''
</code></pre>
<p>最后选择的特征是<code>2</code>和<code>3</code>,也就是后<strong>2个</strong>特征(特征索引是从<code>0</code>开始的)。</p>
<p>从特征得分来看看,后<strong>2个</strong>特征也是得分最高的。</p>
<h2 id="22-包裹式带着模型一起选">2.2. 包裹式:带着模型一起选</h2>
<p><strong>包裹式</strong>方法就像带着模型去"试衣"一样,把特征子集当作不同的"衣服",让模型试穿(训练)后看看效果如何。</p>
<p>根据模型的表现(比如准确性)来决定哪些特征组合最好。</p>
<p>常见的<strong>包裹式</strong>方法包括:</p>
<ul>
<li><strong>递归特征消除</strong>(<code>RFE</code>):不断移除最不重要的特征,直到达到指定数量</li>
<li><strong>穷举搜索</strong>:尝试所有可能的特征组合(计算成本很高)</li>
</ul>
<p>下面的代码示例使用<strong>递归特征消除</strong>(<code>RFE</code>):</p>
<pre><code class="language-python">from sklearn.feature_selection import RFE
from sklearn.ensemble import RandomForestClassifier

# 创建随机森林分类器
model = RandomForestClassifier(random_state=42)

# 创建递归特征消除选择器
selector = RFE(model, n_features_to_select=2, step=1)
selector = selector.fit(X_train, y_train)

# 查看选中的特征
selected_features = selector.get_support(indices=True)
print(f"选中的特征: {selected_features}")
print(f"特征排名: {selector.ranking_}")

# 特征选择后的数据
X_train_selected = selector.transform(X_train)
X_test_selected = selector.transform(X_test)

# 输出特征选择后的数据维度
print(f"原始训练集特征数: {X_train.shape}")
print(f"选择后训练集特征数: {X_train_selected.shape}")

## 输出结果:
'''
选中的特征:
特征排名:
原始训练集特征数: 4
选择后训练集特征数: 2
'''
</code></pre>
<p>选择的特征也是<code>2</code>和<code>3</code>,从特征排名来看,<strong>前两个</strong>特征排名<code>2</code>和<code>3</code>,<strong>后两个</strong>特征并列排名<code>第一</code>。</p>
<h2 id="23-嵌入式在模型里自然选择">2.3. 嵌入式:在模型里自然选择</h2>
<p><strong>嵌入式</strong>方法就像在模型里内置了一个"挑食"机制,让模型在训练过程中自然地倾向于使用某些特征,而忽略其他特征。</p>
<p>这种方法通常通过正则化来实现。</p>
<p>常见的<strong>嵌入式</strong>方法包括:</p>
<ul>
<li><strong>L1正则化</strong>(<code>Lasso</code>):会自动将不重要特征的系数缩放到零</li>
<li><strong>树模型中的特征重要性</strong>:如随机森林、梯度提升树等模型自带的特征重要性评分</li>
</ul>
<p>代码示例:</p>
<pre><code class="language-python">from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LassoCV

# 创建带L1正则化的逻辑回归模型
model = LassoCV(random_state=42)

# 创建嵌入式选择器
selector = SelectFromModel(model, threshold='median')
selector = selector.fit(X_train, y_train)

# 查看选中的特征
selected_features = selector.get_support(indices=True)
print(f"选中的特征: {selected_features}")

# 特征选择后的数据
X_train_selected = selector.transform(X_train)
X_test_selected = selector.transform(X_test)

# 输出特征选择后的数据维度
print(f"原始训练集特征数: {X_train.shape}")
print(f"选择后训练集特征数: {X_train_selected.shape}")

## 输出结果:
'''
选中的特征:
原始训练集特征数: 4
选择后训练集特征数: 2
'''
</code></pre>
<p>同样,最终选择的特征也是<code>2</code>和<code>3</code>。</p>
<h1 id="3-三种方法的对比">3. 三种方法的对比</h1>
<p>选择哪种特征选择方法,取决于你的具体需求和场景,下面是三种方法的比较:</p>
<table>
<thead>
<tr>
<th>方法类型</th>
<th>优点</th>
<th>缺点</th>
<th>适用场景</th>
</tr>
</thead>
<tbody>
<tr>
<td>过滤式</td>
<td>计算效率高,不依赖模型</td>
<td>可能忽略特征与模型的关系</td>
<td>特征数量较少,对模型不敏感的情况</td>
</tr>
<tr>
<td>包裹式</td>
<td>直接考虑模型性能,效果通常较好</td>
<td>计算开销大,容易过拟合</td>
<td>特征数量适中,对性能要求高的情况</td>
</tr>
<tr>
<td>嵌入式</td>
<td>计算效率较高,考虑了特征与模型的关系</td>
<td>通常需要模型本身支持特征选择</td>
<td>需要模型具有稀疏性的情况</td>
</tr>
</tbody>
</table>
<h1 id="4-总结">4. 总结</h1>
<p><strong>特征选择</strong>是机器学习流程中不可忽略的重要环节。</p>
<p>在实际应用中,我们可以尝试多种方法,观察它们对模型性能的影响,有时候,结合多种方法甚至能取得更好的效果。</p>
<p><strong>记住</strong>,特征选择不是一成不变的规则,而是一门需要根据数据和模型不断调整的艺术。</p><br><br>
来源:https://www.cnblogs.com/wang_yb/p/18908033
頁: [1]
查看完整版本: 机器学习中的"食材挑选术":特征选择方法