Operating System | Ubuntu 20.04.03 LTS (Focal Fossa) |
GPU | Nvidia RTX 3080 |
Nvidia Driver Version | 470.74 |
Python Version | 3.8.10 |
CUDA Version | 11.1 |
cuDNN Version | 8.2.0 |
Images
資料夾的所有資料夾取出放在 stanford_dog
的資料夾: 下載連結|- images
|- Image
|- n02085620-Chihuahua
|- n02085782-Japanese_spaniel
‧
‧
‧
‧
‧
|- Stanford_dog
|- n02085620-Chihuahua
|- n02085782-Japanese_spaniel
‧
‧
‧
‧
‧
import os, torch
import numpy as np
import torch.nn as nn
import matplotlib.pyplot as plt
from PIL import Image
import torchvision.transforms as transforms
import torchvision.models as models
from torch.utils.data import Dataset, DataLoader
from torchvision.datasets import ImageFolder
from torchvision import models
from torch import optim
from torchsummary import summary
import time
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(device)
# 實作一個可以讀取 stanford dog (mini) 的 Pytorch dataset
class DogDataset(Dataset):
def __init__(self, filenames, labels, transform):
self.filenames = filenames # 資料集的所有檔名
self.labels = labels # 影像的標籤
self.transform = transform # 影像的轉換方式
def __len__(self):
return len(self.filenames) # return DataSet 長度
def __getitem__(self, idx): # idx: Inedx of filenames
image = Image.open(self.filenames[idx]).convert('RGB')
image = self.transform(image) # Transform image
label = np.array(self.labels[idx])
return image, label # return 模型訓練所需的資訊
normalize = transforms.Normalize(mean = [0.485, 0.456, 0.406], std = [0.229, 0.224, 0.225])
# Transformer
train_transformer = transforms.Compose([
transforms.Resize(256),
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
normalize
])
test_transformer = transforms.Compose([
transforms.Resize(224),
transforms.CenterCrop(224),
transforms.ToTensor(),
normalize
])
def split_Train_Val_Data(data_dir):
dataset = ImageFolder(data_dir)
# 建立 20 類的 list
character = [[] for i in range(len(dataset.classes))]
# print(character)
# 將每一類的檔名依序存入相對應的 list
for x, y in dataset.samples:
character[y].append(x)
train_inputs, test_inputs = [], []
train_labels, test_labels = [], []
for i, data in enumerate(character): # 讀取每個類別中所有的檔名 (i: label, data: filename)
np.random.seed(42)
np.random.shuffle(data)
# -------------------------------------------
# 將每一類都以 8:2 的比例分成訓練資料和測試資料
# -------------------------------------------
num_sample_train = int(len(data) * 0.8)
num_sample_test = len(data) - num_sample_train
# print(str(i) + ': ' + str(len(data)) + ' | ' + str(num_sample_train) + ' | ' + str(num_sample_test))
for x in data[:num_sample_train] : # 前 80% 資料存進 training list
train_inputs.append(x)
train_labels.append(i)
for x in data[num_sample_train:] : # 後 20% 資料存進 testing list
test_inputs.append(x)
test_labels.append(i)
train_dataloader = DataLoader(DogDataset(train_inputs, train_labels, train_transformer),
batch_size = batch_size, shuffle = True)
test_dataloader = DataLoader(DogDataset(test_inputs, test_labels, test_transformer),
batch_size = batch_size, shuffle = False)
return train_dataloader, test_dataloader
# 參數設定
batch_size = 32 # Batch Size
lr = 1e-3 # Learning Rate
epochs = 50 # epoch 次數
data_dir = 'stanford_dog' # 資料夾名稱
train_dataloader, test_dataloader = split_Train_Val_Data(data_dir)
C = models.vgg16(pretrained=True).to(device) # 使用內建的 model
optimizer_C = optim.SGD(C.parameters(), lr = lr) # 選擇你想用的 optimizer
summary(C, (3, 244, 244)) # 利用 torchsummary 的 summary package 印出模型資訊,input size: (3 * 224 * 224)
# Loss function
criterion = nn.CrossEntropyLoss() # 選擇想用的 loss function
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv2d-1 [-1, 64, 244, 244] 1,792
ReLU-2 [-1, 64, 244, 244] 0
Conv2d-3 [-1, 64, 244, 244] 36,928
ReLU-4 [-1, 64, 244, 244] 0
MaxPool2d-5 [-1, 64, 122, 122] 0
Conv2d-6 [-1, 128, 122, 122] 73,856
ReLU-7 [-1, 128, 122, 122] 0
Conv2d-8 [-1, 128, 122, 122] 147,584
ReLU-9 [-1, 128, 122, 122] 0
MaxPool2d-10 [-1, 128, 61, 61] 0
Conv2d-11 [-1, 256, 61, 61] 295,168
ReLU-12 [-1, 256, 61, 61] 0
Conv2d-13 [-1, 256, 61, 61] 590,080
ReLU-14 [-1, 256, 61, 61] 0
Conv2d-15 [-1, 256, 61, 61] 590,080
ReLU-16 [-1, 256, 61, 61] 0
MaxPool2d-17 [-1, 256, 30, 30] 0
Conv2d-18 [-1, 512, 30, 30] 1,180,160
ReLU-19 [-1, 512, 30, 30] 0
Conv2d-20 [-1, 512, 30, 30] 2,359,808
ReLU-21 [-1, 512, 30, 30] 0
Conv2d-22 [-1, 512, 30, 30] 2,359,808
ReLU-23 [-1, 512, 30, 30] 0
MaxPool2d-24 [-1, 512, 15, 15] 0
Conv2d-25 [-1, 512, 15, 15] 2,359,808
ReLU-26 [-1, 512, 15, 15] 0
Conv2d-27 [-1, 512, 15, 15] 2,359,808
ReLU-28 [-1, 512, 15, 15] 0
Conv2d-29 [-1, 512, 15, 15] 2,359,808
ReLU-30 [-1, 512, 15, 15] 0
MaxPool2d-31 [-1, 512, 7, 7] 0
AdaptiveAvgPool2d-32 [-1, 512, 7, 7] 0
Linear-33 [-1, 4096] 102,764,544
ReLU-34 [-1, 4096] 0
Dropout-35 [-1, 4096] 0
Linear-36 [-1, 4096] 16,781,312
ReLU-37 [-1, 4096] 0
Dropout-38 [-1, 4096] 0
Linear-39 [-1, 1000] 4,097,000
================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.68
Forward/backward pass size (MB): 258.51
Params size (MB): 527.79
Estimated Total Size (MB): 786.98
----------------------------------------------------------------
loss_epoch_C = []
train_acc, test_acc = [], []
best_acc, best_auc = 0.0, 0.0
if __name__ == '__main__':
for epoch in range(epochs):
start_time = time.time()
iter = 0
correct_train, total_train = 0, 0
correct_test, total_test = 0, 0
train_loss_C = 0.0
C.train() # 設定 train 或 eval
print('epoch: ' + str(epoch + 1) + ' / ' + str(epochs))
# ---------------------------
# Training Stage
# ---------------------------
for i, (x, label) in enumerate(train_dataloader) :
x, label = x.to(device), label.to(device)
optimizer_C.zero_grad() # 清空梯度
train_output = C(x) # 將訓練資料輸入至模型進行訓練 (Forward propagation)
train_loss = criterion(train_output, label) # 計算 loss
train_loss.backward() # 將 loss 反向傳播
optimizer_C.step() # 更新權重
# 計算訓練資料的準確度 (correct_train / total_train)
_, predicted = torch.max(train_output.data, 1) # 取出預測的 maximum
total_train += label.size(0)
correct_train += (predicted == label).sum()
train_loss_C += train_loss.item()
iter += 1
print('Training epoch: %d / loss_C: %.3f | acc: %.3f' % \
(epoch + 1, train_loss_C / iter, correct_train / total_train))
# --------------------------
# Testing Stage
# --------------------------
C.eval() # 設定 train 或 eval
for i, (x, label) in enumerate(test_dataloader) :
with torch.no_grad(): # 測試階段不需要求梯度
x, label = x.to(device), label.to(device)
test_output = C(x) # 將測試資料輸入至模型進行測試
test_loss = criterion(test_output, label) # 計算 loss
# 計算測試資料的準確度 (correct_test / total_test)
_, predicted = torch.max(test_output.data, 1)
total_test += label.size(0)
correct_test += (predicted == label).sum()
print('Testing acc: %.3f' % (correct_test / total_test))
train_acc.append(100 * (correct_train / total_train).cpu()) # training accuracy
test_acc.append(100 * (correct_test / total_test).cpu()) # testing accuracy
loss_epoch_C.append((train_loss_C / iter)) # loss
end_time = time.time()
print('Cost %.3f(secs)' % (end_time - start_time))
epoch: 1 / 50
Training epoch: 1 / loss_C: 5.587 | acc: 0.014
Testing acc: 0.020
Cost 122.854(secs)
epoch: 2 / 50
Training epoch: 2 / loss_C: 4.714 | acc: 0.040
Testing acc: 0.041
Cost 122.754(secs)
show more (open the raw output data in a text editor) ...
epoch: 50 / 50
Training epoch: 50 / loss_C: 1.147 | acc: 0.678
Testing acc: 0.691
Cost 121.660(secs)
fig_dir = './fig/'
if not os.path.isdir(fig_dir):
os.makedirs(fig_dir)
plt.figure()
plt.plot(list(range(epochs)), loss_epoch_C) # plot your loss
plt.title('Training Loss')
plt.ylabel('loss'), plt.xlabel('epoch')
plt.legend(['loss_C'], loc = 'upper left')
plt.savefig(os.path.join(fig_dir, 'loss.png'))
plt.show()
plt.figure()
plt.plot(list(range(epochs)), train_acc) # plot your training accuracy
plt.plot(list(range(epochs)), test_acc) # plot your testing accuracy
plt.title('Training acc')
plt.ylabel('acc (%)'), plt.xlabel('epoch')
plt.legend(['training acc', 'testing acc'], loc = 'upper left')
plt.savefig(os.path.join(fig_dir, 'acc.png'))
plt.show()
Conda 建立&管理 Python 虛擬環境 建立虛擬環境 步驟一: 確認自己現有環境 tienyi@tienyi:~$ conda env list output: # conda environments:
Feb 20, 2022Python 虛擬環境架設 參考連結 1. 通過 venv 來創造一個虛擬環境: python -m venv <YOUR-PATH> venv 參數介紹: usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear] [--upgrade] [--without-pip] [--prompt PROMPT] ENV_DIR [ENV_DIR ...]
Nov 23, 2021Ubuntu 20.04 安裝 TenserFlow & PyTorch for RTX 30系列 將會安裝以下套件 TensorFlow PyTorch CUDA cuDNN Dependencies and other frameworks like Caffe and Theano(?) 系統需求
Nov 2, 2021or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up