大数跨境

导师:“用Codex把几千个特征全部变成0和1?”我:“模型能跑,效果也不错!”导师:“二值化都没搞懂,就敢说自己会特征工程?”

导师:“用Codex把几千个特征全部变成0和1?”我:“模型能跑,效果也不错!”导师:“二值化都没搞懂,就敢说自己会特征工程?” 机器学习和人工智能AI
2026-11-10
0

哈喽,大家好~

最近收到一个问题:“特征不是越精细越好吗?为什么还要把数据变成只有0和1?”

这个问题很常见。今天我们就来聊聊机器学习中的一种特征预处理方法:二值化(Binarization)。

整个文章,会讲清楚二值化是什么、什么时候有用,并通过一个完整的 Python 案例,观察它对分类模型效果的影响~

01二值化到底是什么?

假设我们有一个特征:用户每天登录次数。

0.5、1.2、3.8、6.0、10.5

如果我们设置阈值为  ,就可以把它变成:

0、0、1、1、1

也就是:低于等于阈值记为0,高于阈值记为1。

数学表达式如下:

其中,  是原始特征,  是阈值,  是二值化后的结果。

你可以这样理解:我们不再关心“登录了多少次”,只关心“是否超过了某个重要标准”。

在 sklearn 中,可以使用 Binarizer:

from sklearn.preprocessing import Binarizer

binarizer = Binarizer(threshold=0)
X_binary = binarizer.fit_transform(X)

这里的 threshold=0 表示:大于0变成1,小于等于0变成0。

02为什么要进行二值化?

二值化主要有几个使用场景。

第一,处理本身就具有“有或无”含义的数据,比如词语是否出现、用户是否点击、设备是否在线。

第二,降低异常值影响。原始数值可能从1到10000变化很大,但二值化后只保留是否超过阈值。

第三,让模型更容易学习某种规则。例如,当温度超过30度时,设备故障概率明显提高,这时“是否超过30度”可能比具体温度更有解释性。

但它也会损失信息。比如特征值分别是4和100,二值化后可能都变成1,模型无法区分它们。

一句话概括的话,就是二值化可以增强规则感,但会牺牲数值细节。

03完整案例

下面我们构造一个分类数据集,比较原始特征和二值化特征在逻辑回归中的表现。

import numpy as np
import matplotlib.pyplot as plt

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, Binarizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, f1_score
from sklearn.decomposition import PCA

# 1. 数据
X, y = make_classification(
    n_samples=2900,
    n_features=6,
    n_informative=4,
    n_redundant=1,
    n_clusters_per_class=2,
    class_sep=1.15,
    random_state=42
)

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, stratify=y, random_state=42
)

# 2. 标准化,避免不同特征量纲影响阈值
scaler = StandardScaler()
X_train_std = scaler.fit_transform(X_train)
X_test_std = scaler.transform(X_test)

# 3. 原始特征模型
raw_model = LogisticRegression(max_iter=1000)
raw_model.fit(X_train_std, y_train)
raw_pred = raw_model.predict(X_test_std)

print("原始特征 Accuracy:",
      round(accuracy_score(y_test, raw_pred), 3))
print("原始特征 F1:",
      round(f1_score(y_test, raw_pred), 3))

# 4. 使用0阈值进行二值化
binarizer = Binarizer(threshold=0)
X_train_bin = binarizer.fit_transform(X_train_std)
X_test_bin = binarizer.transform(X_test_std)

bin_model = LogisticRegression(max_iter=1000)
bin_model.fit(X_train_bin, y_train)
bin_pred = bin_model.predict(X_test_bin)

print("二值化 Accuracy:",
      round(accuracy_score(y_test, bin_pred), 3))
print("二值化 F1:",
      round(f1_score(y_test, bin_pred), 3))

# 5. PCA投影:观察二值化前后的结构
pca = PCA(n_components=2)
X_all_std = scaler.transform(X)
X_all_pca = pca.fit_transform(X_all_std)
X_all_bin = Binarizer(threshold=0).fit_transform(X_all_std)
X_bin_pca = pca.fit_transform(X_all_bin)

plt.figure(figsize=(13, 5))

plt.subplot(1, 2, 1)
plt.scatter(X_all_pca[:, 0], X_all_pca[:, 1],
            c=y, cmap="turbo", s=22, alpha=0.75)
plt.title("Standardized Features + PCA")
plt.xlabel("Principal Component 1")
plt.ylabel("Principal Component 2")
plt.colorbar(label="Class")

plt.subplot(1, 2, 2)
plt.scatter(X_bin_pca[:, 0], X_bin_pca[:, 1],
            c=y, cmap="turbo", s=22, alpha=0.75)
plt.title("Binarized Features + PCA")
plt.xlabel("Principal Component 1")
plt.ylabel("Principal Component 2")
plt.colorbar(label="Class")

plt.tight_layout()
plt.show()

# 6. 比较不同阈值
thresholds = np.linspace(-1.5, 1.5, 25)
acc_list, f1_list = [], []

for threshold in thresholds:
    transformer = Binarizer(threshold=threshold)
    train_bin = transformer.fit_transform(X_train_std)
    test_bin = transformer.transform(X_test_std)

    model = LogisticRegression(max_iter=1000)
    model.fit(train_bin, y_train)
    pred = model.predict(test_bin)

    acc_list.append(accuracy_score(y_test, pred))
    f1_list.append(f1_score(y_test, pred))

plt.figure(figsize=(9, 5))
plt.plot(thresholds, acc_list, "o-", color="#ff3366",
         linewidth=2.5, label="Accuracy")
plt.plot(thresholds, f1_list, "s-", color="#00b4d8",
         linewidth=2.5, label="F1-score")
plt.axvline(0, color="#222222", linestyle="--",
            label="Default threshold = 0")

plt.xlabel("Binarization Threshold")
plt.ylabel("Score")
plt.title("Model Performance under Different Thresholds")
plt.grid(alpha=0.25)
plt.legend()
plt.tight_layout()
plt.show()

第一张图中的 PCA 投影,是把多维数据压缩到二维后进行观察。左图保留了连续数值变化,样本位置通常更加平滑;右图经过二值化后,数据结构会变得更加离散,部分样本可能被压缩到相似区域。

这张图主要帮助我们判断:二值化是否让类别边界更清晰,还是把原本有用的差异抹掉了。

第二张图展示不同阈值下的 Accuracy 和 F1-score。可以看到,阈值并不是越大越好。阈值太低,很多样本会变成1;阈值太高,又可能让大量样本变成0。

所以,实际项目中不能默认使用0,而应该根据验证集效果、业务规则和类别不平衡情况选择阈值。

04使用二值化时要注意什么?

首先,阈值最好只使用训练集确定,不能提前看测试集,否则会造成数据泄漏。

其次,如果不同特征的量纲差异很大,建议先标准化,再进行统一阈值处理。否则,身高、收入、次数等特征直接使用同一个阈值,通常没有实际意义。

最后,二值化不适合所有任务。对于图像像素、传感器读数、价格等信息,数值大小本身往往很重要,直接变成0和1可能导致效果下降。

总结

二值化的核心,就是通过阈值把连续特征转换成0和1。它简单、可解释,适合表达“是否发生”“是否超过标准”这类问题。

但二值化会损失数值细节,阈值也会直接影响模型效果。你可以继续尝试:比较二值化与 MinMaxScaler、StandardScaler 的效果;或者针对每个特征单独搜索最佳阈值。

总之就是说,二值化不是让数据“更高级”,而是把复杂数值转换成更明确的规则。是否值得使用,要看数据特点和验证结果。

最后

最近准备了16大块的内容,124个算法问题的总结,完整的机器学习小册,免费领取~

领取:备注「算法小册」即可~
扫码如有问题,记得添加微信号:xiaobai_ml012

【声明】内容源于网络
0
0
机器学习和人工智能AI
让我们一起期待 AI 带给我们的每一场变革!推送最新行业内最新最前沿人工智能技术!
内容 451
粉丝 0
机器学习和人工智能AI 让我们一起期待 AI 带给我们的每一场变革!推送最新行业内最新最前沿人工智能技术!
总阅读10.4k
粉丝0
内容451