我是开发CNN的新手,目前正在使用PyTorch制作二进制图像分类器。我的数据集严重不平衡,因此我手动增加了测试部分和训练部分的平衡。我有一个班级0(训练集有6500张图像)和班级1(训练集有5200ish图像)。当我尝试使用skorch的fit函数时,我得到的验证准确度等于集合中1类图像的百分比,而我的预测函数仅对所有图像输出1。
这是我改编自CNN的教程,网址为:https://colab.research.google.com/github/dnouri/skorch/blob/master/notebooks/Transfer_Learning.ipynb#scrollTo=cane7VRWW3dO
这是我的CNN :(根据教程改编而成)
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import torchvision.models as models
import numpy as np
from numpy import array
import pandas as pd
from skorch import NeuralNetClassifier
from skorch.helper import predefined_split
from skorch.callbacks import LRScheduler
from skorch.callbacks import Checkpoint
from skorch.callbacks import Freezer
from PIL import Image
import skorch
import os
import cv2
import glob
from sklearn.pipeline import FeatureUnion, Pipeline
from sklearn.preprocessing import StandardScaler, MinMaxScaler, Normalizer
#Define transforms (will be same w/o online transforms)
#Manually augmented earlier
train_transforms = transforms.Compose([
#transforms.RandomResizedCrop(224),
#transforms.RandomHorizontalFlip(),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
val_transforms = transforms.Compose([
#transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
train_ds = datasets.ImageFolder(train_split_path, train_transforms)
val_ds = datasets.ImageFolder(test_aug_split_path, val_transforms)
checkpoint = Checkpoint(
f_params='best_model.pt', monitor='valid_acc_best')
#Using ResNet with some layers for now
class PretrainedModel(nn.Module):
def __init__(self, output_features):
super().__init__()
model = models.resnet152(pretrained=True)
#Don't want to change pretrained weights
for param in model.parameters():
param.requires_grad = False
num_features = model.fc.in_features
fc_layers = nn.Sequential(
nn.Linear(num_features, 4096),
nn.ReLU(inplace=True),
nn.Dropout(p=0.3),
nn.Linear(4096, output_features),
nn.ReLU(inplace=True),
nn.Dropout(p=0.3),
)
model.fc = fc_layers
self.model = model
def forward(self, x):
return self.model(x)
use_cuda = torch.cuda.is_available()
net = NeuralNetClassifier(
module=PretrainedModel,
module__output_features = 2,
criterion=nn.CrossEntropyLoss,
batch_size = 16,
lr=0.0001,
max_epochs=3,
optimizer=optim.Adam,
train_split=predefined_split(val_ds),
callbacks=[checkpoint],
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
)
net.fit(train_ds, y=None)
这是拟合函数的结果:
第1阶段:火车损失= .46有效_acc = .4301有效损失= .6931
第2阶段:火车损失= .6931有效损失= .4301有效损失= .6931
第3阶段:火车损失= .6931有效损失= .4301有效损失= .6931
事实证明,对于该特定数据集,我的验证图像中恰好有43%是1类图像。
y_pred = net.predict(val_ds)给了我以下内容:
array([1,1,1,...,1,1,1],dtype = int64)
我想我有两个问题:
1)我在初始化CNN时是否做错了什么会导致这种情况?
2)是什么原因造成的,我有什么办法可以纠正它?