【问题标题】:SVM working well on test subset fails on whole dataset在测试子集上运行良好的 SVM 在整个数据集上失败
【发布时间】:2021-07-23 23:59:46
【问题描述】:

我使用 sklearn 在大量数据上迭代训练了一个 SVM。每个 csv 文件都是图像的一部分。我用滑动窗口制作了那些。我使用 partial_fit() 来拟合 SVM 和缩放器。特征是图像的 RGBN 值,我想将图像分为两个不同的组 0 和 1。

def trainSVMIterative(directory):

    clf= SGDClassifier(learning_rate = 'constant', eta0 = 0.1, shuffle = False,n_iter_no_change = 5,  warm_start = True )
    sc = StandardScaler()
    firstIter = True
    iter = 0
    for filename in os.listdir(directory):
         if filename.endswith('.csv'):
            pixels = pd.read_csv(os.path.join(directory, filename),sep = ',')
            
            #drop columns containing irelevant information
            pixels = pixels.drop('x', axis = 1)
            pixels = pixels.drop('y', axis = 1)


            #dataset
            X = pixels.drop('label', axis = 1)
            #labels
            Y = pixels['label']

            #prepare training data
            X_train, X_test, y_train, y_test = train_test_split(X,Y,test_size = 0.2, random_state = 42) 

            #fit scaler
            sc = sc.partial_fit(X)

            #scale input
            X_train = sc.transform(X_train)
            X_test = sc.transform(X_test)

            
            #train svm
            if firstIter:
                 clf.partial_fit(X_train,y_train, classes=np.unique(Y))
                 firstIter = False
            else:
                clf.partial_fit(X_train,y_train)
                testPred = clf.predict(X_test)

                print(classification_report(y_test,testPred))

                iter+=1
                print(iter) 

            

    return clf, sc

当我在每次迭代后打印分类报告时,它看起来很好,准确率高达 98%。因此,我假设我的分类器正在正确训练。 为了测试,我从原始图像中提取了一个新的数据框。这一次,没有带有标签的列。我将分类器和定标器传递给我的测试函数

def testClassifier(path, classifier, scaler):
     #opening the original image, same process as in creating the training data
     raster = gdal.Open(path)
     array = tifToImgArray(raster, 'uint8')
     
     # select a part of the image to test on
     windowSize = 1000
     y = 19000
     x = 0
     window = array[y:y + windowSize,x:x + windowSize]

     #create the dataframe
     arrayData = []
 
     for i in range(window.shape[0]):
        for j in range(window.shape[1]):
           
            arrayData.append([i,j,array[i,j,0],array[i,j,1],array[i,j,2],array[i,j,3]])
                          
     dfData = pd.DataFrame(arrayData, columns=['x','y','R','G','B','N'])

     #again drop psoition information
     pixels = dfData.drop('x', axis = 1)
     pixels = pixels.drop('y', axis = 1)

     

     #use scaler 
     pixels = scaler.transform(pixels)
     
     #make prediction
     prediction = classifier.predict(pixels)
     

     image = visualizePrediction(prediction, window, dfData)     
            
            
     return image

我现在的问题是,分类器为每个像素预测标签“1”。我用于测试的数据框 X 与我在一次训练中使用的相同,只是在训练测试数据时没有拆分,我只是使用了整个集合。我真的不明白我做错了什么,因为分类器在 X 的一个子集上工作得很好。我认为这可能是一个问题,即有更多的数据点标记为“1”然后标记为“0”并且我不使用对数据的任何权重。但是,当我将数据集拆分为 X_train 和 X_test 时,为什么它会起作用,因为那里也是如此。 我会在这个问题上提供帮助。 问候

【问题讨论】:

    标签: python machine-learning scikit-learn


    【解决方案1】:
    • 如果我们的模型的准确率非常高,那并不一定意味着它一直都做得很好(它可能在 train_data 上但不是在 test_data 上)。

      示例:假设我们有大约 100 行数据,其中 label1 = 90 #rowslabel0 = 10 #rows。我们使用通常的test_train_split 并训练我们的模型(在我们的例子中,它是一个分类模型)并且看到准确率为 95%。由于我们的模型非常完美,我们部署了它,几天后我们注意到它的预测不如我们训练期间的那么好。原因是因为数据是倾斜的。即使模型预测“label0”错误,准确性仍然会随着“label1”预测占主导地位而提高,我认为这正是您的数据所发生的情况。

    • 我们可以在进行预测后使用Confusion Matrix 进行检查。混淆矩阵评估我们模型的性能。我们还有其他指标,例如 F1 scoreRoc curve,它们也非常有用。

    • 我们可以通过将数据正确分布来解决这个问题。但大多数时候我们缺乏数据,我们拥有的所有数据都是这种倾斜的数据。在这种情况下,我们可以做一些叫做Oversampling and Undersampling的事情。

    【讨论】:

    • 我的问题是我的模型在 test_data 上运行良好,它在 test_data+ train_data 上失败,所以整个数据集。我还检查了 F1 分数,标签 1 的数据为 99%,标签 0 的数据为 50%。对我来说很奇怪的是,模型在它训练过的数据上失败了,而且它预测的数据大多正确地纠正了我的第一个函数。我会尝试你的第二点,只选择平衡的数据块进行训练,看看会发生什么。
    • 既然你说,整体数据有更多的label1,可以安全地假设当你做train_test_split时,拆分test_data有更多的label1。现在想象一下,当它预测 90% label1 正确但 10%label0 失败时,准确度会是多少。是的,准确度会更高,但没用。现在,尝试使用一些平衡的数据,让我知道结果如何。我对每一步的准确性以及混淆矩阵非常好奇,但那是以后的事了。无论如何,请记住总是做一些快速的EDA 以避免此类事情。
    • 平衡数据大大改善了预测,你说得对。我在每一步都查看了混淆矩阵,结果发现 label0 的预测非常糟糕,而 label1 的预测非常好。我想知道的是,模型在每一步都至少有一些正确的 label0 预测,那么为什么在不进行拆分的情况下使用时它会错误地预测相同的点?无论如何,非常感谢你的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-02
    • 2014-01-01
    相关资源
    最近更新 更多