import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
from torch.utils.data import TensorDataset
import torchvision
import os
import shutil
"""
torchvision.datasets.ImageFolder # 从分类的文件夹中创建dataset数据
"""
base_dir = r"./dataset/4weather"
if not os.path.isdir(base_dir):
os.makedirs(base_dir)
train_dir = os.path.join(base_dir, "train")
test_dir = os.path.join(base_dir, "test")
os.mkdir(train_dir)
os.mkdir(test_dir)
train_dir = os.path.join(base_dir, "train")
test_dir = os.path.join(base_dir, "test")
specises = ['cloudy', 'rain', 'shine', 'sunrise']
creation = 0
if creation==1:
for train_or_test in ['train', 'test']:
for spec in specises:
os.mkdir(os.path.join(base_dir, train_or_test, spec))
image_dir = r"./dataset2"
print("os.listdir(image_dir)",os.listdir(image_dir))
for i, img in enumerate(os.listdir(image_dir)):
for spec in specises:
if spec in img:
s = os.path.join(image_dir, img)
if i % 5 == 0:
d = os.path.join(base_dir, "test", spec, img)
else:
d = os.path.join(base_dir, "train", spec, img)
shutil.copy(s, d)
for train_or_test in ["train", "test"]:
for spec in specises:
print(train_or_test, spec, len(os.listdir(os.path.join(base_dir, train_or_test, spec))))
from torchvision import transforms
transform = transforms.Compose([
transforms.Resize((96, 96)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])
train_ds = torchvision.datasets.ImageFolder(train_dir, transform=transform)
test_ds= torchvision.datasets.ImageFolder(test_dir, transform=transform)
print("train_ds.classes:\t", train_ds.classes)
print("train_ds.class_to_idx:\t", train_ds.class_to_idx)
print("len(train_ds):{}\t, len(test_ds):{}\t".format(len(train_ds), len(test_ds)))
BATCHSIZE = 16
train_dl = DataLoader(train_ds, batch_size=BATCHSIZE, shuffle=True)
test_dl = DataLoader(test_ds, batch_size=BATCHSIZE)
imgs, labels = next(iter(train_dl))
print("imgs.shape:\t", imgs.shape)
print("imgs[0]:\t", imgs[0].shape)
im = imgs[0].permute(1, 2, 0)
print("im.shape:\t", im.shape)
im = im.numpy()
print("type(im):\t", type(im))
im = (im + 1) / 2
print("im.max():\t{} \t im.min():\t{}".format(im.max(), im.min()))
print("labels[0]:\t", labels[0])
id_to_class = dict((v, k) for k, v in train_ds.class_to_idx.items())
print("id_to_class:\t", id_to_class)
plt.figure(figsize=(12, 8))
for i, (img, label) in enumerate(zip(imgs[:6], labels[:6])):
img = (img.permute(1, 2, 0).numpy() + 1) / 2
plt.subplot(2, 3, i+1)
plt.title(label.item())
class Net(nn.Module):
def __init__(self):
super(Net, self). __init__()
self.conv1 = nn.Conv2d(3, 16, 3)
self.conv2 = nn.Conv2d(16, 32, 3)
self.conv3 = nn.Conv2d(32, 64, 3)
"""
添加Dropout和Dropout2d
"""
self.drop = nn.Dropout(0.5)
self.drop2d = nn.Dropout2d(0.5)
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(64*10*10, 1024)
self.fc2 = nn.Linear(1024, 256)
self.fc3 = nn.Linear(256, 4)
def forward(self, x):
x = F.relu(self.conv1(x))
x = self.pool(x)
x = F.relu(self.conv2(x))
x = self.pool(x)
x = F.relu(self.conv3(x))
x = self.pool(x)
x = self.drop2d(x)
x = x.view(-1, x.size(1)*x.size(2)*x.size(3))
x = F.relu(self.fc1(x))
"""
添加Dropout层
"""
x = self.drop(x)
x = F.relu(self.fc2(x))
x = self.drop(x)
x = self.fc3(x)
return x
model = Net()
preds = model(imgs)
print("imgs.shape:\t", imgs.shape)
print("preds.shape:\t", preds.shape)
preds = torch.argmax(preds, 1)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print("device:\t", device)
model = model.to(device)
loss_fn = nn.CrossEntropyLoss()
optim = torch.optim.Adam(model.parameters(), lr=0.001)
"""""""""""""""""""""""""""""""""""""""""""""""""""
model.train() 训练模式
model.eval() 预测模式 # 主要影响dropout层 BN层
"""""""""""""""""""""""""""""""""""""""""""""""""""
def fit(epoch, model, trainloader, testloader):
correct = 0
total = 0
running_loss = 0
model.train()
for x, y in trainloader:
x, y = x.to(device), y.to(device)
y_pred = model(x)
loss = loss_fn(y_pred, y)
optim.zero_grad()
loss.backward()
optim.step()
with torch.no_grad():
y_pred = torch.argmax(y_pred, dim=1)
correct += (y_pred == y).sum().item()
total += y.size(0)
running_loss += loss.item()
epoch_loss = running_loss / len(trainloader.dataset)
epoch_acc = correct / total
test_correct = 0
test_total = 0
test_running_loss = 0
model.eval()
with torch.no_grad():
for x, y in testloader:
x, y = x.to(device), y.to(device)
y_pred = model(x)
loss = loss_fn(y_pred, y)
y_pred = torch.argmax(y_pred, dim=1)
test_correct += (y_pred == y).sum().item()
test_total += y.size(0)
test_running_loss += loss.item()
epoch_test_loss = test_running_loss / len(testloader.dataset)
epoch_test_acc = test_correct / test_total
print('epoch: ', epoch,
'loss: ', round(epoch_loss, 3),
'accuracy:', round(epoch_acc, 3),
'test_loss: ', round(epoch_test_loss, 3),
'test_accuracy:', round(epoch_test_acc, 3)
)
return epoch_loss, epoch_acc, epoch_test_loss, epoch_test_acc
epochs = 30
train_loss = []
train_acc = []
test_loss = []
test_acc = []
for epoch in range(epochs):
epoch_loss, epoch_acc, epoch_test_loss, epoch_test_acc = fit(epoch,
model,
train_dl,
test_dl)
train_loss.append(epoch_loss)
train_acc.append(epoch_acc)
test_loss.append(epoch_test_loss)
test_acc.append(epoch_test_acc)
plt.plot(range(1, epochs+1), train_loss, label='train_loss')
plt.plot(range(1, epochs+1), test_loss, label="test_loss")
plt.legend()
plt.show()
plt.plot(range(1, epochs+1), train_acc, label='train_acc')
plt.plot(range(1, epochs+1), test_acc, label="test_acc")
plt.legend()
plt.show()
os.listdir(image_dir) ['cloudy1.jpg', 'cloudy10.jpg', 'cloudy100.jpg', 'cloudy101.jpg', 'cloudy102.jpg', 'cloudy103.jpg', 'cloudy104.jpg', 'cloudy105.jpg', 'cloudy106.jpg', 'cloudy107.jpg', 'cloudy108.jpg', 'cloudy109.jpg', 'cloudy11.jpg', 'cloudy110.jpg', 'cloudy111.jpg', 'cloudy112.jpg', 'cloudy113.jpg', 'cloudy114.jpg', 'cloudy115.jpg', 'cloudy116.jpg', 'cloudy117.jpg', 'cloudy118.jpg', 'cloudy119.jpg', 'cloudy12.jpg', 'cloudy120.jpg', 'cloudy121.jpg', 'cloudy122.jpg', 'cloudy123.jpg', 'cloudy124.jpg', 'cloudy125.jpg', 'cloudy126.jpg', 'cloudy202.jpg', 'cloudy203.jpg', 'cloudy204.jpg', 'cloudy205.jpg', 'cloudy206.jpg', 'cloudy207.jpg', 'cloudy208.jpg', 'cloudy209.jpg', 'cloudy21.jpg', 'cloudy210.jpg', 'cloudy211.jpg', 'cloudy212.jpg', 'cloudy213.jpg', 'cloudy214.jpg', 'cloudy215.jpg', 'cloudy216.jpg', 'cloudy217.jpg', 'cloudy218.jpg', 'cloudy219.jpg', 'cloudy22.jpg'.............]
train cloudy 240
train rain 172
train shine 202
train sunrise 286
test cloudy 60
test rain 43
test shine 51
test sunrise 71
train_ds.classes: ['cloudy', 'rain', 'shine', 'sunrise']
train_ds.class_to_idx: {'cloudy': 0, 'rain': 1, 'shine': 2, 'sunrise': 3}
len(train_ds):900 , len(test_ds):225
imgs.shape: torch.Size([16, 3, 96, 96])
imgs[0]: torch.Size([3, 96, 96])
im.shape: torch.Size([96, 96, 3])
type(im): <class 'numpy.ndarray'>
im.max(): 0.9960784316062927 im.min(): 0.0
labels[0]: tensor(3)
id_to_class: {0: 'cloudy', 1: 'rain', 2: 'shine', 3: 'sunrise'}
imgs.shape: torch.Size([16, 3, 96, 96])
preds.shape: torch.Size([16, 4])
device: cuda:0
epoch: 0 loss: 0.056 accuracy: 0.567 test_loss: 0.039 test_accuracy: 0.778
epoch: 1 loss: 0.04 accuracy: 0.704 test_loss: 0.039 test_accuracy: 0.738
epoch: 2 loss: 0.036 accuracy: 0.759 test_loss: 0.036 test_accuracy: 0.791
epoch: 3 loss: 0.033 accuracy: 0.762 test_loss: 0.034 test_accuracy: 0.8
epoch: 4 loss: 0.033 accuracy: 0.784 test_loss: 0.038 test_accuracy: 0.769
epoch: 5 loss: 0.03 accuracy: 0.801 test_loss: 0.039 test_accuracy: 0.8
epoch: 6 loss: 0.032 accuracy: 0.818 test_loss: 0.055 test_accuracy: 0.804
epoch: 7 loss: 0.031 accuracy: 0.813 test_loss: 0.036 test_accuracy: 0.827
epoch: 8 loss: 0.029 accuracy: 0.823 test_loss: 0.039 test_accuracy: 0.827
epoch: 9 loss: 0.026 accuracy: 0.861 test_loss: 0.036 test_accuracy: 0.836
epoch: 10 loss: 0.026 accuracy: 0.841 test_loss: 0.041 test_accuracy: 0.853
epoch: 11 loss: 0.022 accuracy: 0.866 test_loss: 0.041 test_accuracy: 0.889
epoch: 12 loss: 0.026 accuracy: 0.85 test_loss: 0.044 test_accuracy: 0.778
epoch: 13 loss: 0.026 accuracy: 0.846 test_loss: 0.045 test_accuracy: 0.844
epoch: 14 loss: 0.022 accuracy: 0.858 test_loss: 0.029 test_accuracy: 0.867
epoch: 15 loss: 0.017 accuracy: 0.901 test_loss: 0.035 test_accuracy: 0.88
epoch: 16 loss: 0.017 accuracy: 0.903 test_loss: 0.036 test_accuracy: 0.884
epoch: 17 loss: 0.016 accuracy: 0.908 test_loss: 0.042 test_accuracy: 0.876
epoch: 18 loss: 0.016 accuracy: 0.92 test_loss: 0.026 test_accuracy: 0.902
epoch: 19 loss: 0.016 accuracy: 0.913 test_loss: 0.043 test_accuracy: 0.88
epoch: 20 loss: 0.015 accuracy: 0.924 test_loss: 0.052 test_accuracy: 0.893
epoch: 21 loss: 0.011 accuracy: 0.944 test_loss: 0.029 test_accuracy: 0.893
epoch: 22 loss: 0.01 accuracy: 0.952 test_loss: 0.035 test_accuracy: 0.938
epoch: 23 loss: 0.014 accuracy: 0.926 test_loss: 0.04 test_accuracy: 0.92
epoch: 24 loss: 0.01 accuracy: 0.943 test_loss: 0.04 test_accuracy: 0.916
epoch: 25 loss: 0.01 accuracy: 0.947 test_loss: 0.037 test_accuracy: 0.92
epoch: 26 loss: 0.01 accuracy: 0.95 test_loss: 0.044 test_accuracy: 0.92
epoch: 27 loss: 0.017 accuracy: 0.913 test_loss: 0.03 test_accuracy: 0.893
epoch: 28 loss: 0.011 accuracy: 0.941 test_loss: 0.039 test_accuracy: 0.907
epoch: 29 loss: 0.014 accuracy: 0.942 test_loss: 0.026 test_accuracy: 0.88