SVM在测试子集上表现良好,但在整个数据集上失败

我使用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 = ',')                        #删除包含不相关信息的列            pixels = pixels.drop('x', axis = 1)            pixels = pixels.drop('y', axis = 1)            #数据集            X = pixels.drop('label', axis = 1)            #标签            Y = pixels['label']            #准备训练数据            X_train, X_test, y_train, y_test = train_test_split(X,Y,test_size = 0.2, random_state = 42)             #拟合缩放器            sc = sc.partial_fit(X)            #缩放输入            X_train = sc.transform(X_train)            X_test = sc.transform(X_test)                        #训练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):     #打开原始图像,与创建训练数据的过程相同     raster = gdal.Open(path)     array = tifToImgArray(raster, 'uint8')          #选择图像的一部分进行测试     windowSize = 1000     y = 19000     x = 0     window = array[y:y + windowSize,x:x + windowSize]     #创建数据框     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'])     #再次删除位置信息     pixels = dfData.drop('x', axis = 1)     pixels = pixels.drop('y', axis = 1)          #使用缩放器      pixels = scaler.transform(pixels)          #进行预测     prediction = classifier.predict(pixels)          image = visualizePrediction(prediction, window, dfData)                                  return image

现在我的问题是,分类器对每个像素都预测为标签“1”。我在测试中使用的X数据框与训练运行中使用的数据框相同,只是没有将数据分为训练和测试数据,我只是使用了整个数据集。我不太明白我做错了什么,因为分类器在X的一个子集上表现得相当好。我在想可能是标记为“1”的数据点比标记为“0”的数据点多,而我没有对数据进行加权。但另一方面,为什么在将数据集分割成X_train和X_test时它能工作,因为在这种情况下也是如此。我希望能在这方面得到帮助。谢谢


回答:

  • 如果我们的模型准确率非常高,并不一定意味着它一直表现得很好(它可能在训练数据上表现好,但在测试数据上不一定)。

    例如:假设我们有100行数据,其中label1 = 90 #行label0 = 10 #行。我们通常进行test_train_split并训练我们的模型(在我们的例子中,是一个分类模型),并看到准确率为95%。由于我们的模型如此完美,我们部署了它,几天后我们注意到它的预测效果不如训练期间那么好。原因是数据是倾斜的。即使模型错误地预测了“label0”,准确率仍然会增加,因为“label1”的预测主导了其他,我认为这正是你数据中发生的情况。

  • 我们可以在进行预测后使用混淆矩阵来检查这一点。混淆矩阵评估我们模型的性能。我们还有其他指标,如F1分数ROC曲线,这些也非常有用。

  • 我们可以通过使数据达到正确的分布来解决这个问题。但大多数时候我们缺乏数据,我们所有的数据都是这种倾斜数据。在这种情况下,我们可以做一些称为过采样和欠采样的事情。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注