python - 模型预测不在目标中的类(零数组)
问题描述
我已经使用 MultiLabelBinarizer 对目标变量进行了编码。然后,我以这种方式从转换结果中创建了一个新的 DataFrame
y_trans = pd.DataFrame(MultiLabelBinarizer().fit_transform(y))
这里是head()
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
-----------------------------------------------------------------------
0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0
2 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0
3 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
4 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
我使用创建训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_trans, y_trans, random_state=0)
在拟合 aRandomForest
或 a后KNN
,预测X_test
变量会返回一个数组,其中一些预测是这样的
array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
这样的类不存在于编码的目标变量中,因为
len(y_trans.where(y_trans == [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]).dropna())
实际上是 0。
我不明白为什么会这样。 有点相关的问题。
重现我的问题
我提供了要下载的编码特征和标签。它们以二进制格式腌制。从那里,重现我的错误的步骤很简单
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
import pickle
X_trans = pickle.load(open('features.pkl', 'rb'))
y_trans = pickle.load(open('target.pkl', 'rb'))
X_train, X_test, y_train, y_test = train_test_split(X_trans, y_trans, random_state=0)
rfc = RandomForestClassifier(random_state=0)
rfc.fit(X_train, y_train)
print(rfc.predict(X_test)[1])
打印预测中的第二个值将返回[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
我的分类目标
我的目标是创建一个分类器,它可以预测至少一个“正确的类”,由条目中的 1 表示。例如, y 的第一个条目是[0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0]
。我会认为是正确的
[0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0]
但这是一个评估问题,一旦预测正确,就会发生。正如我所说,不能有“空洞”的预测。有 18 个类和 127 个独特的组合,其中没有一个是[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
.
Sklearn示例有同样的“问题”
在这一点上,这个输出必须有意义。但我无法弄清楚。注意:在这个例子中KNN
,我展示了使用的分类器,RandomForest
但如果我使用KNN
,我会遇到同样的问题。
from sklearn.datasets import make_multilabel_classification
from sklearn.multioutput import MultiOutputClassifier
from sklearn.neighbors import KNeighborsClassifier
X, y = make_multilabel_classification(n_classes=18, random_state=0)
clf = MultiOutputClassifier(KNeighborsClassifier()).fit(X, y)
clf.predict(X)[3]
>>> array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
拆分为训练集和测试集时同样适用
from sklearn.datasets import make_multilabel_classification
from sklearn.multioutput import MultiOutputClassifier
from sklearn.neighbors import KNeighborsClassifier
X, y = make_multilabel_classification(n_classes=18, random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0, test_size=0.2)
clf = MultiOutputClassifier(KNeighborsClassifier()).fit(X_train, y_train)
clf.predict(X_test)[8]
>>> array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
解决方案
首先,感谢问题的质量。
我认为这里有几件事需要解释:
- 您的分类目标:您需要定义自己的指标来衡量您所描述的内容。(参见sklearn 中的 make_scorer 函数)。这是第一步,因为如果无法衡量改进是什么,就无法改进模型。
- 接下来,在训练模型时,您需要调整模型参数(称为超参数)以优化您的分数。为了快速解释,您选择一组参数,训练您的模型,并检查测试集上的分数。您通过修改参数进行迭代以优化测试分数。一个简单的方法是使用sklearn 的 GridSearchCV。
- 现在,回答您的问题:您的模型独立地预测您的 18 个类别中的每一个样本是否属于此类。这就是为什么在某些情况下,您可以拥有一个似乎不属于任何类的样本。
你能为这个做什么 ?
- 首先,您需要检查您的模型是否正确拟合,并调整超参数以提高分数。目前,它严重过度拟合(训练分数远高于测试分数)。您可能会发现数据中没有足够的信号使其无法正常工作。
- 也许另一种模型可以帮助您获得更好的结果,具体取决于数据的拓扑结构(您需要尝试看看)
- 您还可以使用 : 获取每个类的预测概率,
rfc.predict_proba
这将允许您设置与默认 0.5 不同的阈值,甚至选择更高的阈值。
推荐阅读
- android - 在真实设备中启动时签名的 apk 崩溃
- python - 调整 x 轴大小并保存信息
- reactjs - TS React 数据导入:“TS2322:类型 '{ data: { key1: string; }; }' 不可分配给类型 'IntrinsicAttributes & Props'。”
- c - 如何使用 dart ffi 为给定的 C 结构编写绑定?
- java - 使用for循环并行化函数
- javascript - 如何在 firestore 触发的函数中写入 firestore?
- django - 找不到 Django 模板 - 尝试了不同的位置
- feathersjs - 羽毛唯一的客户ID?
- git - 用于微服务和部署的单一 GIT 存储库
- python - 我正在尝试保存我所做的聚类结果并显示此错误消息“int”对象不可下标