python - 分类标签使用交叉熵损失,准确率不变| 深度学习 pytorch
问题描述
我有一个关于我最近的项目的问题。
我一直在尝试用PyTorch
它来训练我的多类分类工作。我的图像数据集中有3
标签(即0
-> 无、1
-> 左、2
-> 右)。我已经用作nn.CrossEntropyLoss()
我的损失函数和Adam
优化器。但是,训练结果看起来是这样的,准确率根本没有变化。
==> Building new CNN model ...
==> Initialize CUDA support for CNN model ...
==> Preparing RcCar Image dataset ...
==> Start training ...
Iteration: 1 | Loss: 1.3453235626220703 | Training accuracy: 70% | Test accuracy: 43%
==> Saving model ...
/usr/local/lib/python3.6/dist-packages/torch/serialization.py:251: UserWarning: Couldn't retrieve source code for container of type SimpleCNN. It won't be checked for correctness upon loading.
"type " + obj.__name__ + ". It won't be checked "
Iteration: 2 | Loss: 0.9048898816108704 | Training accuracy: 70% | Test accuracy: 43%
Iteration: 3 | Loss: 0.873579740524292 | Training accuracy: 70% | Test accuracy: 43%
Iteration: 4 | Loss: 0.8702362179756165 | Training accuracy: 70% | Test accuracy: 43%
Iteration: 5 | Loss: 0.8713874220848083 | Training accuracy: 70% | Test accuracy: 43%
Iteration: 6 | Loss: 0.8639134168624878 | Training accuracy: 70% | Test accuracy: 43%
Iteration: 7 | Loss: 0.8590883612632751 | Training accuracy: 70% | Test accuracy: 43%
Iteration: 8 | Loss: 0.8576076626777649 | Training accuracy: 70% | Test accuracy: 43%
Iteration: 9 | Loss: 0.8523686528205872 | Training accuracy: 70% | Test accuracy: 43%
Iteration: 10 | Loss: 0.8462777137756348 | Training accuracy: 70% | Test accuracy: 43%
我在想这是否是因为我选择的损失函数不合适,或者我必须将标签一次性编码成
[
[0,0,1],
[0,1,0],
...
]
像这样。
我附上了我的自定义数据集部分。拜托,拜托,请帮我解决这个问题。谢谢!
def RcCarImageLoader(root, batch_size_train, batch_size_test):
"""
RC Car Image Loader.
Args:
train_root:
test_root:
batch_size_train:
batch_size_test:
Return:
train_loader:
test_loader:
"""
# Normalize training set together with augmentation
transform_train = transforms.Compose([
transforms.RandomResizedCrop(64),
transforms.RandomRotation(10),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
# Normalize test set same as training set without augmentation
transform_test = transforms.Compose([
transforms.Resize(64),
transforms.CenterCrop(64),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
# Loading Tiny ImageNet dataset
print("==> Preparing RcCar Image dataset ...")
train_set = ImageLoader(csv_filename="./train.csv", transform=transform_train)
train_loader = torch.utils.data.DataLoader(
train_set, batch_size=batch_size_train, num_workers=2)
test_set = ImageLoader(csv_filename="./test.csv", transform=transform_test, train=False)
test_loader = torch.utils.data.DataLoader(
test_set, batch_size=batch_size_test, num_workers=2)
return train_loader, test_loader
def image_loader(path):
"""Image Loader helper function."""
return Image.open(path.rstrip("\n")).convert('RGB')
class ImageLoader(Dataset):
"""Image Loader for Tiny ImageNet."""
def __init__(self, csv_filename, transform=None, train=True, loader=image_loader):
"""
Image Loader Builder.
Args:
base_path: path to triplets.txt
filenames_filename: text file with each line containing the path to an image e.g., `images/class1/sample.JPEG`
triplets_filename: A text file with each line containing three images
transform: torchvision.transforms
loader: loader for each image
"""
self.transform = transform
self.loader = loader
self.train_flag = train
# load training data
if self.train_flag:
train_data = []
csv_file = pd.read_csv(csv_filename)
self.train_label = np.asarray(csv_file.iloc[:, 1])
train_img_names = np.asarray(csv_file.iloc[:, 0])
for train_img_name in train_img_names:
train_img = self.loader(os.path.join("./train/", train_img_name))
train_data.append(train_img)
self.train_data = train_data
# train_label_one_hot = [[0 for _ in range(3)] for _ in range(len(train_label))]
# for i, row in enumerate(train_label_one_hot):
# row[train_label[i]] = 1
#
# self.train_label = np.asarray(train_label_one_hot)
# load test data
else:
test_data = []
csv_file = pd.read_csv(csv_filename)
self.test_label = np.asarray(csv_file.iloc[:, 1])
test_img_names = np.asarray(csv_file.iloc[:, 0])
for test_img_name in test_img_names:
test_img = self.loader(os.path.join("./test/", test_img_name))
test_data.append(test_img)
self.test_data = test_data
# test_label_one_hot = [[0 for _ in range(3)] for _ in range(len(test_label))]
# for i, row in enumerate(test_label_one_hot):
# row[test_label[i]] = 1
#
# self.test_label = np.asarray(test_label_one_hot)
def __getitem__(self, index):
"""Get image and label in dataset."""
# get training images
if self.train_flag:
img = self.train_data[index]
label = self.train_label[index]
if self.transform is not None:
img = self.transform(img)
return (img, label)
else:
img = self.test_data[index]
label = self.test_label[index]
if self.transform is not None:
img = self.transform(img)
return (img, label)
def __len__(self):
if self.train_flag:
return len(self.train_label)
else:
return len(self.test_label)
解决方案
您对损失函数和 one-hot 编码的猜测是正确的。进行一次热编码并使用BCEloss并告诉我。
推荐阅读
- math - How to convert coordinates from one Spherical system to another rotated by 90 degrees without going to Cartesian
- python - 为什么只有在使用 pytest 进行单元测试时才找到模块?
- git - 如何将多个 git repos 重新组合成一个 repo 并保留历史记录?
- azure - 可以使用 Azure Kubernetes Service 或 Azure Service Fabric 来部署和管理本地 kubernetes 集群吗?
- asp.net-core - ASPNET CORE InvalidOperationException:无法重定向到授权端点,配置可能丢失或无效
- android - Android Studio API 29 及更高版本的模拟器立即崩溃
- javascript - 无法读取未定义 Javascript 的属性“拆分”
- flutter - Flutter中,如何在屏幕底部放置一个ListView
- terminal - 奇怪的终端提示
- c# - 是否有一种干净的方法可以从在 WSL 下运行的 dotnet 核心应用程序访问 AppData?