【问题标题】:SMOTE initialisation expects n_neighbors <= n_samples, but n_samples < n_neighborsSMOTE 初始化需要 n_neighbors <= n_samples,但 n_samples < n_neighbors
【发布时间】:2018-08-29 23:01:37
【问题描述】:

我已经对数据进行了预清理,下面是前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 的数量,但无济于事,任何提示或建议将不胜感激。感谢阅读。

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

编辑:

Full Traceback

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

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

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

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

【问题讨论】:

  • 错误信息是不言自明的,不是吗?我猜您的X_train 中需要更多样本(行)
  • 请添加错误的完整堆栈跟踪。
  • 另外请告诉我们你的班级不平衡。有多少类,每个类有多少样本?
  • 感谢大家的回复,我已尽力在对原始帖子的编辑中解决您的问题。如果有什么我可以纠正的,请告诉我!

标签: scikit-learn knn tf-idf oversampling imblearn


【解决方案1】:

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

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

【讨论】:

  • 非常正确,但请考虑下次添加更多详细信息。这有助于人们更好地解决问题。
【解决方案2】:

为什么会发生:

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

我是如何解决的:

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

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

xr, yr = SMOTE(k_neighbors=3).fit_resample(x, y)

【讨论】:

    【解决方案3】:

    我认为可以使用代码:

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

    【讨论】:

      【解决方案4】:

      尝试为 SMOTE 执行以下代码

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

      这对我有用。

      【讨论】:

        【解决方案5】:

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

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

        2. 使用SMOTE 类的ratio 参数排除n_samples

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

        4. 结合 3 和 4 解决方案:创建一个使用 SMOTERandomOversampler 的管道,以满足 smoted 类的条件 n_neighbors

        【讨论】:

        • 感谢您的回答,将课程数量减少到例如几十年(仅用于预测)而不是个别年份?在此期间,我会继续采纳您的建议!
        • 我无法调查 (1) 和 (2),因为有些班级只有一个样本。但是,我能够成功地流水线化 RandomOverSampler(和/或 FakeSampler 类),然后是 SMOTE 和分类器,如图所示:make_pipeline(sampler, SMOTE(), clf)。我会继续这个,看看我能用它做什么!感谢您的宝贵时间!
        • @Dbercules:嗨,你能指导我吗,你是怎么做管道的?我试过sm = SMOTE(random_state=42)rm = RandomOverSampler(random_state=42)my_pipe = make_pipeline(sm, rm)X_res, Y_res = my_pipe.fit_resample(X, y)但是得到了错误,和标题问题一样
        猜你喜欢
        • 1970-01-01
        • 2023-03-14
        • 2018-05-05
        • 2015-07-12
        • 1970-01-01
        • 2020-09-11
        • 2019-03-18
        • 1970-01-01
        • 2023-03-09
        相关资源
        最近更新 更多