sklearn.datasets.make_classification无法生成平衡类
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sklearn.datasets.make_classification无法生成平衡类相关的知识,希望对你有一定的参考价值。
我正在尝试使用sklearn库中的make_classification
来生成分类任务的数据,我希望每个类都有4个样本。
如果类的数量小于19,则行为是正常的。
from sklearn.datasets import make_blobs, make_classification
import numpy as np
data = make_classification(n_samples=76, n_features=5, n_informative=5, n_redundant=0, n_repeated=0,
n_classes=19, n_clusters_per_class=1, weights=None, flip_y=0, class_sep=1.0,
shuffle=False, random_state=101)
print(data[1])
[ 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5
6 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9 10 10 10 10 11 11 11 11
12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 15 16 16 16 16 17 17 17 17
18 18 18 18]
但是,如果类的数量等于或大于20,则第一类将具有5个样本,而最后一个类将仅具有3个样本,这是不平衡的。
data = make_classification(n_samples=80, n_features=5, n_informative=5, n_redundant=0, n_repeated=0,
n_classes=20, n_clusters_per_class=1, weights=None, flip_y=0, class_sep=1.0,
shuffle=False, random_state=101)
print(data[1])
[ 0 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5
5 6 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9 10 10 10 10 11 11 11
11 12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 15 16 16 16 16 17 17 17
17 18 18 18 18 19 19 19]
检查文档时,我发现weight
参数控制了classes
的比例:
weights
:浮点列表或无(默认值=无)分配给每个班级的样本比例。如果为None,那么类是平衡的。请注意,如果len(权重)== n_classes - 1,则自动推断最后一个类权重。如果权重总和超过1,则可以返回多个n_samples样本。
因此,我尝试使用以下代码显式输入比例。
data = make_classification(n_samples=80, n_features=5, n_informative=5, n_redundant=0, n_repeated=0,
n_classes=20, n_clusters_per_class=1, weights=list(np.ones(20)), flip_y=0, class_sep=1.0,
shuffle=False, random_state=101)
print(data[1])
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0]
然而,生成的类是完全错误的。
我不确定为什么这个函数表现得像这样。当n_classes
大于或等于20时,如何确保平衡类?
虽然没有明确提及并且令人困惑,但参数weights
需要“比例”的样本。它不会自动将数字转换为比例。
因此,如果样本总数= 80并且您想要将40个样本分配给第1类,则该比例将变为0.5
。
但是,您提供的比例为:
[1.0, 1.0, 1.0, 1.0,.................., 1.0, 1.0, 1.0, 1.0]
那是错误的根源。该方法需要1.0作为第一类(在您的情况下为0)并忽略所有其他类。
这样做:
n_classes = 20
weights=list(np.ones(20)/n_classes) <== Making proportions correct
data = make_classification(n_samples=80, n_features=5, n_informative=5, n_redundant=0, n_repeated=0,
n_classes=n_classes, n_clusters_per_class=1, weights=weights, flip_y=0, class_sep=1.0,
shuffle=False, random_state=101)
正确返回:
array([ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4,
4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8,
8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12,
12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16,
17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19])
最后一行:
如果权重总和超过1,则可以返回多个n_samples样本。
似乎增加了混乱。
当您将1.0
作为所有类别的比例传递时,它应该返回80 * 20 = 1600个样本,每个类别80个。
但它没有这样做。它在内部正确生成样本,但之后只返回前80个样本(由n_samples
param定义)。这就是为什么你只在生成的数据中得到一个类(0)。你应该在github:https://github.com/scikit-learn/scikit-learn/issues的页面上发布这个问题
以上是关于sklearn.datasets.make_classification无法生成平衡类的主要内容,如果未能解决你的问题,请参考以下文章