我使用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曲线,这些也非常有用。
-
我们可以通过使数据达到正确的分布来解决这个问题。但大多数时候我们缺乏数据,我们所有的数据都是这种倾斜数据。在这种情况下,我们可以做一些称为过采样和欠采样的事情。