12

我已经预先清理了数据,下面显示了前 4 行的格式:

     [IN] df.head()

    [OUT]   Year    cleaned
         0  1909    acquaint hous receiv follow letter clerk crown...
         1  1909    ask secretari state war whether issu statement...
         2  1909    i beg present petit sign upward motor car driv...
         3  1909    i desir ask secretari state war second lieuten...
         4  1909    ask secretari state war whether would introduc...

我调用了 train_test_split() 如下:

     [IN] X_train, X_test, y_train, y_test = train_test_split(df['cleaned'], df['Year'], random_state=2)
   [Note*] `X_train` and `y_train` are now Pandas.core.series.Series of shape (1785,) and `X_test` and `y_test` are also Pandas.core.series.Series of shape (595,)

然后,我使用以下 TfidfVectorizer 和拟合/转换过程对 X 训练和测试数据进行了矢量化处理:

     [IN] v = TfidfVectorizer(decode_error='replace', encoding='utf-8', stop_words='english', ngram_range=(1, 1), sublinear_tf=True)
          X_train = v.fit_transform(X_train)
          X_test = v.transform(X_test)

我现在处于通常应用分类器等的阶段(如果这是一组平衡的数据)。但是,我初始化了 imblearn 的 SMOTE ()类(以执行过采样)...

     [IN] smote_pipeline = make_pipeline_imb(SMOTE(), classifier(random_state=42))
          smote_model = smote_pipeline.fit(X_train, y_train)
          smote_prediction = smote_model.predict(X_test)

...但这会导致:

     [OUT] ValueError: "Expected n_neighbors <= n_samples, but n_samples = 5, n_neighbors = 6.

我试图减少 n_neighbors 的数量,但无济于事,任何提示或建议将不胜感激。谢谢阅读。

-------------------------------------------------- -------------------------------------------------- --------------------------------

编辑:

完整回溯

数据集/数据框 ( df) 包含两列 2380 行,如上所示df.head()X_train包含 1785 行格式为字符串 ( df['cleaned']) 的行,y_train还包含 1785 行格式为字符串 ( df['Year'])。

TfidfVectorizer()使用:X_train和的后矢量化X_test分别从pandas.core.series.Series形状 '(1785,)' 和 '(595,)' 转换scipy.sparse.csr.csr_matrix为形状 '(1785, 126459)' 和 '(595, 126459)'。

至于类的数量:使用Counter(),我计算出有 199 个类(年),类的每个实例都附加到上述df['cleaned']数据的一个元素,其中包含从文本语料库中提取的字符串列表。

此过程的目标是根据词汇表自动确定/猜测输入文本数据的年份、十年或世纪(任何程度的分类都可以!)。

4

5 回答 5

22

由于训练集中大约有 200 个类和 1800 个样本,因此每个类平均有 9 个样本。错误消息的原因是a)可能数据不是完全平衡的,并且有少于6个样本的类和b)邻居的数量是6。您的问题的一些解决方案:

  1. 计算 199 个类中的最小样本数(n_samples),并选择n_neighbors小于或等于 n_samples 的 SMOTE 类的参数。

  2. ratio使用类的参数排除对具有 n_samples < n_neighbors 的类进行过采样SMOTE

  3. 使用RandomOverSampler没有类似限制的类。

  4. 结合 3 和 4 解决方案:创建一个管道,该管道使用SMOTERandomOversampler以满足 smoted 类的条件 n_neighbors <= n_samples 的方式使用,并在不满足条件时使用随机过采样。

于 2018-03-22T00:35:01.647 回答
5

尝试为 SMOTE 执行以下代码

oversampler=SMOTE(kind='regular',k_neighbors=2)

这对我有用。

于 2019-06-28T14:29:33.613 回答
4

为什么会发生:

在我的情况下,它发生是因为对于某些值/类别,我的样本数量只有 1 个。由于 SMOTE 基于 KNN 概念,因此无法对 1 个采样值应用 SMOTE。

我是如何解决的:

由于这 1 个采样值/类别等同于异常值,因此我将它们从数据集中删除,然后应用 SMOTE 并且它起作用了。

还可以尝试减小k_neighbors参数以使其工作

xr, yr = SMOTE(k_neighbors=3).fit_resample(x, y)
于 2021-04-10T16:49:47.910 回答
1

当一个类别中的样本数量非常少(小于k_neighbors参数)时,就会发生这种情况。

您可以通过调用异常值来删除这些值,也可以将k_neighbors参数更改为解决方案。

于 2021-05-08T10:34:45.317 回答
0

我认为可以使用以下代码:

采样器 = SMOTE(ratio={1: 1927, 0: 300},random_state=0)

于 2019-09-03T09:27:34.077 回答