MLP to CNN
CNN-OnlyConv
Trước khi vào bài code thì chúng ta sẽ xem nhược điểm của các mô hình như MLP trên một số tập dữ liệu như FashionMNIST, Cifar10. Tôi sẽ áp dụng Conv để so sánh độ hiệu quả.
MLP_FashionMNIST_ReLU_He_Adam
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
import torch.nn.init as init
# Check if GPU is available
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
Data
# Load CFashionMNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.FashionMNIST(root='data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=1024, num_workers=10, shuffle=True, drop_last=True)
testset = torchvision.datasets.FashionMNIST(root='data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=1024, num_workers=10, shuffle=False)
import matplotlib.pyplot as plt
import numpy as np
# Function to display the images
def imshow(img):
img = img*0.5 + 0.5
np_img = img.numpy()
plt.imshow(np.transpose(np_img, (1, 2, 0)))
plt.show()
for i, (images, labels) in enumerate(trainloader, 0):
# Plot some images
imshow(torchvision.utils.make_grid(images[:8])) # Display 8 images from the batch
break
Model
model = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10)
)
# Initialize the weights using He initialization
for layer in model:
if isinstance(layer, nn.Linear):
init.kaiming_uniform_(layer.weight, nonlinearity='relu')
if layer.bias is not None:
layer.bias.data.fill_(0)
model = model.to(device)
print(model)
Loss, Optimizer, and Evaluation Function
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.0001)
# Function to compute loss and accuracy for test set
def evaluate(model, testloader, criterion):
model.eval()
test_loss = 0.0
running_correct = 0
total = 0
with torch.no_grad():
for images, labels in testloader:
# Move inputs and labels to the device
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
test_loss += loss.item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
accuracy = 100 * running_correct / total
test_loss = test_loss / len(testloader)
return test_loss, accuracy
Train
# some parameter
train_losses = []
train_accuracies = []
test_losses = []
test_accuracies = []
max_epoch = 250
# train
for epoch in range(max_epoch):
model.train()
running_loss = 0.0
running_correct = 0 # to track number of correct predictions
total = 0 # to track total number of samples
for i, (inputs, labels) in enumerate(trainloader, 0):
# Move inputs and labels to the device
inputs, labels = inputs.to(device), labels.to(device)
# Zero the parameter gradients
optimizer.zero_grad()
# Forward pass
outputs = model(inputs)
loss = criterion(outputs, labels)
running_loss += loss.item()
# Determine class predictions and track accuracy
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
# Backward pass and optimization
loss.backward()
optimizer.step()
epoch_accuracy = 100 * running_correct / total
epoch_loss = running_loss / (i + 1)
test_loss, test_accuracy = evaluate(model, testloader, criterion)
print(f"Epoch [{epoch + 1}/{max_epoch}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
# save for plot
train_losses.append(epoch_loss)
train_accuracies.append(epoch_accuracy)
test_losses.append(test_loss)
test_accuracies.append(test_accuracy)
import matplotlib.pyplot as plt
plt.plot(train_losses, label='train_losses')
plt.plot(test_losses, label='test_losses')
plt.legend()
import matplotlib.pyplot as plt
plt.plot(train_accuracies, label='train_accuracy')
plt.plot(test_accuracies, label='test_accuracy')
plt.legend()
MLP_Cifar10_ReLU_He_Adam
Data
# Load CFashionMNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,0.5, 0.5), (0.5,0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=1024, num_workers=10, shuffle=True, drop_last=True)
testset = torchvision.datasets.CIFAR10(root='data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=1024, num_workers=10, shuffle=False)
import matplotlib.pyplot as plt
import numpy as np
# Function to display the images
def imshow(img):
img = img*0.5 + 0.5
np_img = img.numpy()
plt.imshow(np.transpose(np_img, (1, 2, 0)))
plt.show()
for i, (images, labels) in enumerate(trainloader, 0):
# Plot some images
imshow(torchvision.utils.make_grid(images[:8])) # Display 8 images from the batch
break
Model
model = nn.Sequential(
nn.Flatten(),
nn.Linear(32*32*3, 256),
nn.ReLU(),
nn.Linear(256, 10)
)
# Initialize the weights
for layer in model:
if isinstance(layer, nn.Linear):
init.kaiming_uniform_(layer.weight, nonlinearity='relu')
if layer.bias is not None:
layer.bias.data.fill_(0)
model = model.to(device)
print(model)
Loss, Optimizer, and Evaluation Function
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.0001)
# Function to compute loss and accuracy for test set
def evaluate(model, testloader, criterion):
model.eval()
test_loss = 0.0
running_correct = 0
total = 0
with torch.no_grad():
for images, labels in testloader:
# Move inputs and labels to the device
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
test_loss += loss.item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
accuracy = 100 * running_correct / total
test_loss = test_loss / len(testloader)
return test_loss, accuracy
Train
# some parameter
train_losses = []
train_accuracies = []
test_losses = []
test_accuracies = []
max_epoch = 250
# train
for epoch in range(max_epoch):
model.train()
running_loss = 0.0
running_correct = 0 # to track number of correct predictions
total = 0 # to track total number of samples
for i, (inputs, labels) in enumerate(trainloader, 0):
# Move inputs and labels to the device
inputs, labels = inputs.to(device), labels.to(device)
# Zero the parameter gradients
optimizer.zero_grad()
# Forward pass
outputs = model(inputs)
loss = criterion(outputs, labels)
running_loss += loss.item()
# Determine class predictions and track accuracy
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
# Backward pass and optimization
loss.backward()
optimizer.step()
epoch_accuracy = 100 * running_correct / total
epoch_loss = running_loss / (i + 1)
test_loss, test_accuracy = evaluate(model, testloader, criterion)
print(f"Epoch [{epoch + 1}/{max_epoch}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
# save for plot
train_losses.append(epoch_loss)
train_accuracies.append(epoch_accuracy)
test_losses.append(test_loss)
test_accuracies.append(test_accuracy)
import matplotlib.pyplot as plt
plt.plot(train_losses, label='train_losses')
plt.plot(test_losses, label='test_losses')
plt.legend()
import matplotlib.pyplot as plt
plt.plot(train_accuracies, label='train_accuracy')
plt.plot(test_accuracies, label='test_accuracy')
plt.legend()
MLP_Cifar10_ReLU_He_Adam_2H
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
import torch.nn.init as init
# Check if GPU is available
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
Data
# Load CFashionMNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,0.5, 0.5), (0.5,0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=1024, num_workers=10, shuffle=True, drop_last=True)
testset = torchvision.datasets.CIFAR10(root='data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=1024, num_workers=10, shuffle=False)
import matplotlib.pyplot as plt
import numpy as np
# Function to display the images
def imshow(img):
img = img*0.5 + 0.5
np_img = img.numpy()
plt.imshow(np.transpose(np_img, (1, 2, 0)))
plt.show()
for i, (images, labels) in enumerate(trainloader, 0):
# Plot some images
imshow(torchvision.utils.make_grid(images[:8])) # Display 8 images from the batch
break
Model
model = nn.Sequential(
nn.Flatten(),
nn.Linear(32*32*3, 256),
nn.ReLU(),
nn.Linear(256, 256),
nn.ReLU(),
nn.Linear(256, 10)
)
# Initialize the weights using He initialization
for layer in model:
if isinstance(layer, nn.Linear):
init.kaiming_uniform_(layer.weight, nonlinearity='relu')
if layer.bias is not None:
layer.bias.data.fill_(0)
model = model.to(device)
print(model)
Loss, Optimizer, and Evaluation Function
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.0001)
# Function to compute loss and accuracy for test set
def evaluate(model, testloader, criterion):
model.eval()
test_loss = 0.0
running_correct = 0
total = 0
with torch.no_grad():
for images, labels in testloader:
# Move inputs and labels to the device
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
test_loss += loss.item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
accuracy = 100 * running_correct / total
test_loss = test_loss / len(testloader)
return test_loss, accuracy
Train
# some parameter
train_losses = []
train_accuracies = []
test_losses = []
test_accuracies = []
max_epoch = 250
# train
for epoch in range(max_epoch):
model.train()
running_loss = 0.0
running_correct = 0 # to track number of correct predictions
total = 0 # to track total number of samples
for i, (inputs, labels) in enumerate(trainloader, 0):
# Move inputs and labels to the device
inputs, labels = inputs.to(device), labels.to(device)
# Zero the parameter gradients
optimizer.zero_grad()
# Forward pass
outputs = model(inputs)
loss = criterion(outputs, labels)
running_loss += loss.item()
# Determine class predictions and track accuracy
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
# Backward pass and optimization
loss.backward()
optimizer.step()
epoch_accuracy = 100 * running_correct / total
epoch_loss = running_loss / (i + 1)
test_loss, test_accuracy = evaluate(model, testloader, criterion)
print(f"Epoch [{epoch + 1}/{max_epoch}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
# save for plot
train_losses.append(epoch_loss)
train_accuracies.append(epoch_accuracy)
test_losses.append(test_loss)
test_accuracies.append(test_accuracy)
import matplotlib.pyplot as plt
plt.plot(train_losses, label='train_losses')
plt.plot(test_losses, label='test_losses')
plt.legend()
import matplotlib.pyplot as plt
plt.plot(train_accuracies, label='train_accuracy')
plt.plot(test_accuracies, label='test_accuracy')
plt.legend()
MLP_Cifar10_ReLU_He_Adam_3H
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
import torch.nn.init as init
# Check if GPU is available
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
Data
# Load CFashionMNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,0.5, 0.5), (0.5,0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=1024, num_workers=10, shuffle=True, drop_last=True)
testset = torchvision.datasets.CIFAR10(root='data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=1024, num_workers=10, shuffle=False)
import matplotlib.pyplot as plt
import numpy as np
# Function to display the images
def imshow(img):
img = img*0.5 + 0.5
np_img = img.numpy()
plt.imshow(np.transpose(np_img, (1, 2, 0)))
plt.show()
for i, (images, labels) in enumerate(trainloader, 0):
# Plot some images
imshow(torchvision.utils.make_grid(images[:8])) # Display 8 images from the batch
break
Model
model = nn.Sequential(
nn.Flatten(),
nn.Linear(32*32*3, 256),
nn.ReLU(),
nn.Linear(256, 256),
nn.ReLU(),
nn.Linear(256, 256),
nn.ReLU(),
nn.Linear(256, 10)
)
# Initialize the weights using Xavier Glorot initialization
for layer in model:
if isinstance(layer, nn.Linear):
init.kaiming_uniform_(layer.weight, nonlinearity='relu')
if layer.bias is not None:
layer.bias.data.fill_(0)
model = model.to(device)
print(model)
Loss, Optimizer, and Evaluation Function
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.0001)
# Function to compute loss and accuracy for test set
def evaluate(model, testloader, criterion):
model.eval()
test_loss = 0.0
running_correct = 0
total = 0
with torch.no_grad():
for images, labels in testloader:
# Move inputs and labels to the device
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
test_loss += loss.item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
accuracy = 100 * running_correct / total
test_loss = test_loss / len(testloader)
return test_loss, accuracy
Train
# some parameter
train_losses = []
train_accuracies = []
test_losses = []
test_accuracies = []
max_epoch = 250
# train
for epoch in range(max_epoch):
model.train()
running_loss = 0.0
running_correct = 0 # to track number of correct predictions
total = 0 # to track total number of samples
for i, (inputs, labels) in enumerate(trainloader, 0):
# Move inputs and labels to the device
inputs, labels = inputs.to(device), labels.to(device)
# Zero the parameter gradients
optimizer.zero_grad()
# Forward pass
outputs = model(inputs)
loss = criterion(outputs, labels)
running_loss += loss.item()
# Determine class predictions and track accuracy
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
# Backward pass and optimization
loss.backward()
optimizer.step()
epoch_accuracy = 100 * running_correct / total
epoch_loss = running_loss / (i + 1)
test_loss, test_accuracy = evaluate(model, testloader, criterion)
print(f"Epoch [{epoch + 1}/{max_epoch}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
# save for plot
train_losses.append(epoch_loss)
train_accuracies.append(epoch_accuracy)
test_losses.append(test_loss)
test_accuracies.append(test_accuracy)
import matplotlib.pyplot as plt
plt.plot(train_losses, label='train_losses')
plt.plot(test_losses, label='test_losses')
plt.legend()
import matplotlib.pyplot as plt
plt.plot(train_accuracies, label='train_accuracy')
plt.plot(test_accuracies, label='test_accuracy')
plt.legend()
FashionMNIST_CNN_onlyConv2d
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
import torch.nn.init as init
# Check if GPU is available
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
Data
# Load CFashionMNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.FashionMNIST(root='data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=1024, num_workers=10, shuffle=True, drop_last=True)
testset = torchvision.datasets.FashionMNIST(root='data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=1024, num_workers=10, shuffle=False)
import matplotlib.pyplot as plt
import numpy as np
# Function to display the images
def imshow(img):
img = img*0.5 + 0.5
np_img = img.numpy()
plt.imshow(np.transpose(np_img, (1, 2, 0)))
plt.show()
for i, (images, labels) in enumerate(trainloader, 0):
# Plot some images
imshow(torchvision.utils.make_grid(images[:8])) # Display 8 images from the batch
break
Model
import torch
import torch.nn as nn
from torchsummary import summary
class CustomModel(nn.Module):
def __init__(self):
super(CustomModel, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=7)
self.conv2 = nn.Conv2d(32, 64, kernel_size=7)
self.conv3 = nn.Conv2d(64, 128, kernel_size=7)
self.conv4 = nn.Conv2d(128, 256, kernel_size=7)
self.flatten = nn.Flatten()
self.dense1 = nn.Linear(4*4*256, 128)
self.dense2 = nn.Linear(128, 10)
self.relu = nn.ReLU()
def forward(self, x):
x = self.relu(self.conv1(x))
x = self.relu(self.conv2(x))
x = self.relu(self.conv3(x))
x = self.relu(self.conv4(x))
x = self.flatten(x)
x = self.relu(self.dense1(x))
x = self.dense2(x)
return x
model = CustomModel()
model = model.to(device)
# Print model
summary(model, (1, 28, 28))
Loss, Optimizer, and Evaluation Function
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-5)
# Function to compute loss and accuracy for test set
def evaluate(model, testloader, criterion):
model.eval()
test_loss = 0.0
running_correct = 0
total = 0
with torch.no_grad():
for images, labels in testloader:
# Move inputs and labels to the device
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
test_loss += loss.item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
accuracy = 100 * running_correct / total
test_loss = test_loss / len(testloader)
return test_loss, accuracy
Train
# some parameter
train_losses = []
train_accuracies = []
test_losses = []
test_accuracies = []
max_epoch = 250
# train
for epoch in range(max_epoch):
model.train()
running_loss = 0.0
running_correct = 0 # to track number of correct predictions
total = 0 # to track total number of samples
for i, (inputs, labels) in enumerate(trainloader, 0):
# Move inputs and labels to the device
inputs, labels = inputs.to(device), labels.to(device)
# Zero the parameter gradients
optimizer.zero_grad()
# Forward pass
outputs = model(inputs)
loss = criterion(outputs, labels)
running_loss += loss.item()
# Determine class predictions and track accuracy
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
# Backward pass and optimization
loss.backward()
optimizer.step()
epoch_accuracy = 100 * running_correct / total
epoch_loss = running_loss / (i + 1)
test_loss, test_accuracy = evaluate(model, testloader, criterion)
print(f"Epoch [{epoch + 1}/{max_epoch}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
# save for plot
train_losses.append(epoch_loss)
train_accuracies.append(epoch_accuracy)
test_losses.append(test_loss)
test_accuracies.append(test_accuracy)
import matplotlib.pyplot as plt
plt.plot(train_losses, label='train_losses')
plt.plot(test_losses, label='test_losses')
plt.legend()
import matplotlib.pyplot as plt
plt.plot(train_accuracies, label='train_accuracy')
plt.plot(test_accuracies, label='test_accuracy')
plt.legend()
Cifar10_CNN_onlyConv2d
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
import torch.nn.init as init
# Check if GPU is available
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
Data
# Load CFashionMNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=1024, num_workers=10, shuffle=True, drop_last=True)
testset = torchvision.datasets.CIFAR10(root='data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=1024, num_workers=10, shuffle=False)
import matplotlib.pyplot as plt
import numpy as np
# Function to display the images
def imshow(img):
img = img*0.5 + 0.5
np_img = img.numpy()
plt.imshow(np.transpose(np_img, (1, 2, 0)))
plt.show()
for i, (images, labels) in enumerate(trainloader, 0):
# Plot some images
imshow(torchvision.utils.make_grid(images[:8])) # Display 8 images from the batch
break
Model
import torch
import torch.nn as nn
from torchsummary import summary
class CustomModel(nn.Module):
def __init__(self):
super(CustomModel, self).__init__()
self.conv1 = nn.Conv2d(3, 32, kernel_size=7)
self.conv2 = nn.Conv2d(32, 64, kernel_size=7)
self.conv3 = nn.Conv2d(64, 128, kernel_size=7)
self.conv4 = nn.Conv2d(128, 256, kernel_size=7)
self.flatten = nn.Flatten()
self.dense1 = nn.Linear(8*8*256, 128)
self.dense2 = nn.Linear(128, 10)
self.relu = nn.ReLU()
def forward(self, x):
x = self.relu(self.conv1(x))
x = self.relu(self.conv2(x))
x = self.relu(self.conv3(x))
x = self.relu(self.conv4(x))
x = self.flatten(x)
x = self.relu(self.dense1(x))
x = self.dense2(x)
return x
model = CustomModel()
model = model.to(device)
# Print model
summary(model, (3, 32, 32))
Loss, Optimizer, and Evaluation Function
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=5e-5)
# Function to compute loss and accuracy for test set
def evaluate(model, testloader, criterion):
model.eval()
test_loss = 0.0
running_correct = 0
total = 0
with torch.no_grad():
for images, labels in testloader:
# Move inputs and labels to the device
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
test_loss += loss.item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
accuracy = 100 * running_correct / total
test_loss = test_loss / len(testloader)
return test_loss, accuracy
Train
# some parameter
train_losses = []
train_accuracies = []
test_losses = []
test_accuracies = []
max_epoch = 250
# train
for epoch in range(max_epoch):
model.train()
running_loss = 0.0
running_correct = 0 # to track number of correct predictions
total = 0 # to track total number of samples
for i, (inputs, labels) in enumerate(trainloader, 0):
# Move inputs and labels to the device
inputs, labels = inputs.to(device), labels.to(device)
# Zero the parameter gradients
optimizer.zero_grad()
# Forward pass
outputs = model(inputs)
loss = criterion(outputs, labels)
running_loss += loss.item()
# Determine class predictions and track accuracy
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
# Backward pass and optimization
loss.backward()
optimizer.step()
epoch_accuracy = 100 * running_correct / total
epoch_loss = running_loss / (i + 1)
test_loss, test_accuracy = evaluate(model, testloader, criterion)
print(f"Epoch [{epoch + 1}/{max_epoch}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
# save for plot
train_losses.append(epoch_loss)
train_accuracies.append(epoch_accuracy)
test_losses.append(test_loss)
test_accuracies.append(test_accuracy)
import matplotlib.pyplot as plt
plt.plot(train_losses, label='train_losses')
plt.plot(test_losses, label='test_losses')
plt.legend()
import matplotlib.pyplot as plt
plt.plot(train_accuracies, label='train_accuracy')
plt.plot(test_accuracies, label='test_accuracy')
plt.legend()
Downsampling
Trong đoạn code dươi sẽ downsampling bằng 3 cách:
- MaxPooling
- AveragePooling
- Interpolate
FashionMNIST_mp
Data
# Load CFashionMNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.FashionMNIST(root='data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=1024, num_workers=10, shuffle=True, drop_last=True)
testset = torchvision.datasets.FashionMNIST(root='data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=1024, num_workers=10, shuffle=False)
import matplotlib.pyplot as plt
import numpy as np
# Function to display the images
def imshow(img):
img = img*0.5 + 0.5
np_img = img.numpy()
plt.imshow(np.transpose(np_img, (1, 2, 0)))
plt.show()
for i, (images, labels) in enumerate(trainloader, 0):
# Plot some images
imshow(torchvision.utils.make_grid(images[:8])) # Display 8 images from the batch
break
Model
import torch
import torch.nn as nn
from torchsummary import summary
class CustomModel(nn.Module):
def __init__(self):
super(CustomModel, self).__init__()
self.conv = nn.Conv2d(1, 32, kernel_size=5)
self.pool = nn.MaxPool2d(2, 2)
self.flatten = nn.Flatten()
self.dense1 = nn.Linear(12*12*32, 128)
self.dense2 = nn.Linear(128, 10)
self.relu = nn.ReLU()
def forward(self, x):
x = self.conv(x)
x = self.relu(x)
x = self.pool(x)
x = self.flatten(x)
x = self.relu(self.dense1(x))
x = self.dense2(x)
return x
model = CustomModel()
model = model.to(device)
# Print model
summary(model, (1, 28, 28))
Loss, Optimizer, and Evaluation Function
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-4)
# Function to compute loss and accuracy for test set
def evaluate(model, testloader, criterion):
model.eval()
test_loss = 0.0
running_correct = 0
total = 0
with torch.no_grad():
for images, labels in testloader:
# Move inputs and labels to the device
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
test_loss += loss.item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
accuracy = 100 * running_correct / total
test_loss = test_loss / len(testloader)
return test_loss, accuracy
Train
# some parameter
train_losses = []
train_accuracies = []
test_losses = []
test_accuracies = []
max_epoch = 150
# train
for epoch in range(max_epoch):
model.train()
running_loss = 0.0
running_correct = 0 # to track number of correct predictions
total = 0 # to track total number of samples
for i, (inputs, labels) in enumerate(trainloader, 0):
# Move inputs and labels to the device
inputs, labels = inputs.to(device), labels.to(device)
# Zero the parameter gradients
optimizer.zero_grad()
# Forward pass
outputs = model(inputs)
loss = criterion(outputs, labels)
running_loss += loss.item()
# Determine class predictions and track accuracy
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
# Backward pass and optimization
loss.backward()
optimizer.step()
epoch_accuracy = 100 * running_correct / total
epoch_loss = running_loss / (i + 1)
test_loss, test_accuracy = evaluate(model, testloader, criterion)
print(f"Epoch [{epoch + 1}/{max_epoch}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
# save for plot
train_losses.append(epoch_loss)
train_accuracies.append(epoch_accuracy)
test_losses.append(test_loss)
test_accuracies.append(test_accuracy)
import matplotlib.pyplot as plt
plt.plot(train_losses, label='train_losses')
plt.plot(test_losses, label='test_losses')
plt.legend()
import matplotlib.pyplot as plt
plt.plot(train_accuracies, label='train_accuracy')
plt.plot(test_accuracies, label='test_accuracy')
plt.legend()
FashionMNIST_ap
Model
import torch
import torch.nn as nn
from torchsummary import summary
class CustomModel(nn.Module):
def __init__(self):
super(CustomModel, self).__init__()
self.conv = nn.Conv2d(1, 32, kernel_size=5)
self.pool = nn.AvgPool2d(2, 2)
self.flatten = nn.Flatten()
self.dense1 = nn.Linear(12*12*32, 128)
self.dense2 = nn.Linear(128, 10)
self.relu = nn.ReLU()
def forward(self, x):
x = self.conv(x)
x = self.relu(x)
x = self.pool(x)
x = self.flatten(x)
x = self.relu(self.dense1(x))
x = self.dense2(x)
return x
model = CustomModel()
model = model.to(device)
# Print model
summary(model, (1, 28, 28))
Loss, Optimizer, and Evaluation Function
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-4)
# Function to compute loss and accuracy for test set
def evaluate(model, testloader, criterion):
model.eval()
test_loss = 0.0
running_correct = 0
total = 0
with torch.no_grad():
for images, labels in testloader:
# Move inputs and labels to the device
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
test_loss += loss.item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
accuracy = 100 * running_correct / total
test_loss = test_loss / len(testloader)
return test_loss, accuracy
Train
# some parameter
train_losses = []
train_accuracies = []
test_losses = []
test_accuracies = []
max_epoch = 150
# train
for epoch in range(max_epoch):
model.train()
running_loss = 0.0
running_correct = 0 # to track number of correct predictions
total = 0 # to track total number of samples
for i, (inputs, labels) in enumerate(trainloader, 0):
# Move inputs and labels to the device
inputs, labels = inputs.to(device), labels.to(device)
# Zero the parameter gradients
optimizer.zero_grad()
# Forward pass
outputs = model(inputs)
loss = criterion(outputs, labels)
running_loss += loss.item()
# Determine class predictions and track accuracy
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
# Backward pass and optimization
loss.backward()
optimizer.step()
epoch_accuracy = 100 * running_correct / total
epoch_loss = running_loss / (i + 1)
test_loss, test_accuracy = evaluate(model, testloader, criterion)
print(f"Epoch [{epoch + 1}/{max_epoch}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
# save for plot
train_losses.append(epoch_loss)
train_accuracies.append(epoch_accuracy)
test_losses.append(test_loss)
test_accuracies.append(test_accuracy)
import matplotlib.pyplot as plt
plt.plot(train_losses, label='train_losses')
plt.plot(test_losses, label='test_losses')
plt.legend()
import matplotlib.pyplot as plt
plt.plot(train_accuracies, label='train_accuracy')
plt.plot(test_accuracies, label='test_accuracy')
plt.legend()
FashionMNIST_resize
Model
import torch
import torch.nn as nn
from torchsummary import summary
class ResizeLayer(nn.Module):
def __init__(self, scale_factor, mode='bilinear', align_corners=False):
super(ResizeLayer, self).__init__()
self.scale_factor = scale_factor
self.mode = mode
self.align_corners = align_corners
def forward(self, x):
return F.interpolate(x, scale_factor=self.scale_factor, mode=self.mode, align_corners=self.align_corners)
class CustomModel(nn.Module):
def __init__(self):
super(CustomModel, self).__init__()
self.conv = nn.Conv2d(1, 32, kernel_size=5)
self.resize = ResizeLayer(0.5)
self.flatten = nn.Flatten()
self.dense1 = nn.Linear(12*12*32, 128)
self.dense2 = nn.Linear(128, 10)
self.relu = nn.ReLU()
def forward(self, x):
x = self.conv(x)
x = self.relu(x)
x = self.resize(x)
x = self.flatten(x)
x = self.relu(self.dense1(x))
x = self.dense2(x)
return x
model = CustomModel()
model = model.to(device)
# Print model
summary(model, (1, 28, 28))
Loss, Optimizer, and Evaluation Function
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-4)
# Function to compute loss and accuracy for test set
def evaluate(model, testloader, criterion):
model.eval()
test_loss = 0.0
running_correct = 0
total = 0
with torch.no_grad():
for images, labels in testloader:
# Move inputs and labels to the device
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
test_loss += loss.item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
accuracy = 100 * running_correct / total
test_loss = test_loss / len(testloader)
return test_loss, accuracy
Train
# some parameter
train_losses = []
train_accuracies = []
test_losses = []
test_accuracies = []
max_epoch = 150
# train
for epoch in range(max_epoch):
model.train()
running_loss = 0.0
running_correct = 0 # to track number of correct predictions
total = 0 # to track total number of samples
for i, (inputs, labels) in enumerate(trainloader, 0):
# Move inputs and labels to the device
inputs, labels = inputs.to(device), labels.to(device)
# Zero the parameter gradients
optimizer.zero_grad()
# Forward pass
outputs = model(inputs)
loss = criterion(outputs, labels)
running_loss += loss.item()
# Determine class predictions and track accuracy
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
# Backward pass and optimization
loss.backward()
optimizer.step()
epoch_accuracy = 100 * running_correct / total
epoch_loss = running_loss / (i + 1)
test_loss, test_accuracy = evaluate(model, testloader, criterion)
print(f"Epoch [{epoch + 1}/{max_epoch}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
# save for plot
train_losses.append(epoch_loss)
train_accuracies.append(epoch_accuracy)
test_losses.append(test_loss)
test_accuracies.append(test_accuracy)
import matplotlib.pyplot as plt
plt.plot(train_losses, label='train_losses')
plt.plot(test_losses, label='test_losses')
plt.legend()
import matplotlib.pyplot as plt
plt.plot(train_accuracies, label='train_accuracy')
plt.plot(test_accuracies, label='test_accuracy')
plt.legend()
Transition_CNN
Tradition
!pip install opencv-python scikit-image
from typing import Union, List
import time
import PIL
from PIL import Image
import torch
import torch.nn as nn
import torchvision
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import numpy as np
import cv2
import matplotlib.pyplot as plt
1. Dataset
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=None)
test_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=None)
len(train_dataset), len(test_dataset)
def collate_fn(batch):
images, labels = zip(*batch)
return (list(images), torch.tensor(labels))
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, collate_fn=collate_fn, num_workers=4)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False, collate_fn=collate_fn, num_workers=4)
len(train_loader), len(test_loader)
2. Model
# Computer Vision Feature Extraction
class CVF_Extraction(nn.Module):
def __init__(self, num_filters=12, device='cpu'):
super().__init__()
self.num_filters = num_filters
self.device = device
def forward(self, images: List[PIL.Image.Image]):
x = []
for image in images:
image = np.array(image)
feature_images = self._extract(image)
feature_normalized = CVF_Extraction._normalize(feature_images)
x.append(feature_normalized)
x = torch.stack(x) # (N, C, H, W)
return x.to(device)
def _extract(self, image):
width, height, chanel = image.shape
features = []
for c in range(chanel):
bi_image = image[:,:,c]
sobel_image = CVF_Extraction._sobel(bi_image)
scharr_image = CVF_Extraction._scharr(bi_image)
laplacian_image = CVF_Extraction._laplacian(bi_image)
chanel_feature = torch.stack((
torch.from_numpy(bi_image),
sobel_image,
scharr_image,
laplacian_image
), dim=0)
features.append(chanel_feature)
features = torch.stack(features)
return features.view(-1, width, height)
@staticmethod
def _normalize(input_tensor):
_min = input_tensor.min()
_max = input_tensor.max()
normalized = (input_tensor - _min) / (_max - _min)
return normalized
@staticmethod
def _sobel(image, ksize=3):
sobel_x = cv2.Sobel(image, cv2.CV_32F, 1, 0, ksize=ksize)
sobel_y = cv2.Sobel(image, cv2.CV_32F, 0, 1, ksize=ksize)
sobel_x = torch.from_numpy(sobel_x)
sobel_y = torch.from_numpy(sobel_y)
sobel_magnitude = torch.hypot(sobel_x, sobel_y)
return sobel_magnitude
@staticmethod
def _scharr(image):
scharr_x = cv2.Scharr(image, cv2.CV_32F, 1, 0)
scharr_y = cv2.Scharr(image, cv2.CV_32F, 0, 1)
scharr_x = torch.from_numpy(scharr_x)
scharr_y = torch.from_numpy(scharr_y)
scharr_magnitude = torch.hypot(scharr_x, scharr_y)
return scharr_magnitude
@staticmethod
def _laplacian(image):
laplacian_img = cv2.Laplacian(image, cv2.CV_32F)
laplacian_img = torch.from_numpy(laplacian_img)
return laplacian_img
class SimpleImageCLS(nn.Module):
def __init__(self,
features: CVF_Extraction,
img_size=32):
super().__init__()
self.features = features
self.avgpool = nn.AvgPool2d((2, 2))
self.relu = nn.ReLU()
self.flatten = nn.Flatten(1)
in_features = int(self.features.num_filters*(img_size/2)**2)
self.fc1 = nn.Linear(in_features=in_features, out_features=128)
self.fc2 = nn.Linear(in_features=128, out_features=10)
def forward(self, x):
x = self.features(x)
x = self.relu(x)
x = self.avgpool(x)
x = self.flatten(x)
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return x
3. Evaluate
def evaluate(model, test_loader, criterion, device):
model.eval()
test_loss = 0.0
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
labels = labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
test_loss += loss.item()
correct +=(predicted == labels).sum().item()
test_loss = test_loss / len(test_loader)
accuracy = 100* correct / total
return test_loss, accuracy
4. Train
def train_model(model, train_loader, test_loader, optimizer, criterion, num_epochs, device):
since = time.perf_counter()
history = {
"train_losses": [],
"train_accuracies": [],
"test_losses": [],
"test_accuracies": []
}
model.to(device)
for epoch in range(num_epochs):
model.train()
running_loss = 0.0
running_correct = 0
total = 0
for images, labels in train_loader:
labels = labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
running_loss += loss.item()
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
loss.backward()
optimizer.step()
epoch_loss = running_loss / len(train_loader)
epoch_accuracy = 100* running_correct / total
test_loss, test_accuracy = evaluate(model, test_loader, criterion, device)
print(f"Epoch [{epoch + 1}/{num_epochs}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
history['train_losses'].append(epoch_loss)
history['train_accuracies'].append(epoch_accuracy)
history['test_losses'].append(test_loss)
history['test_accuracies'].append(test_accuracy)
time_elapsed = time.perf_counter() - since
print(f"Training complete in {time_elapsed//3600}h {time_elapsed%3600//60}m {int(time_elapsed%60)}s with {num_epochs} epochs")
return history
device = 'cuda'
num_epochs = 100
LR = 0.001
criterion = nn.CrossEntropyLoss()
# num_filters = (raw_image + sobel + scharr + laplacian) * raw_chanel
# = 4 * 3 = 12
cv_features = CVF_Extraction(num_filters=12, device=device)
cv_moddel = model = SimpleImageCLS(features=cv_features)
optimizer = torch.optim.Adam(cv_moddel.parameters(), lr=LR)
cv_history = train_model(model, train_loader, test_loader, optimizer, criterion, num_epochs, device)
5. Plot the result
def plot_result(history):
train_accuracies = history['train_accuracies']
test_accuracies = history['test_accuracies']
train_losses = history['train_losses']
test_losses = history['test_losses']
plt.figure(figsize=(8, 8))
plt.subplot(2, 1, 1)
plt.plot(train_accuracies, label='Training Accuracy')
plt.plot(test_accuracies, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.ylabel('Accuracy')
plt.ylim([min(plt.ylim()),100])
plt.title('Training and Validation Accuracy')
plt.subplot(2, 1, 2)
plt.plot(train_losses, label='Training Loss')
plt.plot(test_losses, label='Validation Loss')
plt.legend(loc='upper right')
plt.ylabel('Binary Cross Entropy')
plt.title('Training and Validation Loss')
plt.xlabel('epoch')
plt.show()
plot_result(cv_history)
CNN
from typing import Union, List
import time
import torch
import torch.nn as nn
import torchvision
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import numpy as np
import cv2
import matplotlib.pyplot as plt
1. Dataset
transform = transforms.Compose([
transforms.ToTensor()
])
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
len(train_dataset), len(test_dataset)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)
len(train_loader), len(test_loader)
2. Model
# Deep Feature Extraction
class DF_Extracion(nn.Module):
def __init__(self, num_filters=64, kernel_size=3, device='cpu'):
super().__init__()
self.num_filters = num_filters
self.device = device
self.conv1 = nn.Conv2d(3, self.num_filters, kernel_size=kernel_size, padding='same')
self.relu = nn.ReLU()
def forward(self, x):
x = self.conv1(x)
return x
class SimpleImageCLS(nn.Module):
def __init__(self,
features: DF_Extracion,
img_size=32):
super().__init__()
self.features = features
self.avgpool = nn.AvgPool2d((2, 2))
self.relu = nn.ReLU()
self.flatten = nn.Flatten(1)
in_features = int(self.features.num_filters*(img_size/2)**2)
self.fc1 = nn.Linear(in_features=in_features, out_features=128)
self.fc2 = nn.Linear(in_features=128, out_features=10)
def forward(self, x):
x = self.features(x)
x = self.relu(x)
x = self.avgpool(x)
x = self.flatten(x)
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return x
3. Evaluate
def evaluate(model, test_loader, criterion, device):
model.eval()
test_loss = 0.0
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
test_loss += loss.item()
correct +=(predicted == labels).sum().item()
test_loss = test_loss / len(test_loader)
accuracy = 100* correct / total
return test_loss, accuracy
4. Train
def train_model(model, train_loader, test_loader, optimizer, criterion, num_epochs, device):
since = time.perf_counter()
history = {
"train_losses": [],
"train_accuracies": [],
"test_losses": [],
"test_accuracies": []
}
model.to(device)
for epoch in range(num_epochs):
model.train()
running_loss = 0.0
running_correct = 0
total = 0
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
running_loss += loss.item()
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
running_correct += (predicted == labels).sum().item()
loss.backward()
optimizer.step()
epoch_loss = running_loss / len(train_loader)
epoch_accuracy = 100* running_correct / total
test_loss, test_accuracy = evaluate(model, test_loader, criterion, device)
print(f"Epoch [{epoch + 1}/{num_epochs}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%, Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.2f}%")
history['train_losses'].append(epoch_loss)
history['train_accuracies'].append(epoch_accuracy)
history['test_losses'].append(test_loss)
history['test_accuracies'].append(test_accuracy)
time_elapsed = time.perf_counter() - since
print(f"Training complete in {time_elapsed//3600}h {time_elapsed%3600//60}m {int(time_elapsed%60)}s with {num_epochs} epochs")
return history
device = 'cuda'
num_epochs = 100
LR = 0.001
criterion = nn.CrossEntropyLoss()
deep_features = DF_Extracion(num_filters=12, device=device)
deep_moddel = model = SimpleImageCLS(features=deep_features)
optimizer = torch.optim.Adam(deep_moddel.parameters(), lr=LR)
deep_history = train_model(model, train_loader, test_loader, optimizer, criterion, num_epochs, device)
5. Plot the result
def plot_result(history):
train_accuracies = history['train_accuracies']
test_accuracies = history['test_accuracies']
train_losses = history['train_losses']
test_losses = history['test_losses']
plt.figure(figsize=(8, 8))
plt.subplot(2, 1, 1)
plt.plot(train_accuracies, label='Training Accuracy')
plt.plot(test_accuracies, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.ylabel('Accuracy')
plt.ylim([min(plt.ylim()),100])
plt.title('Training and Validation Accuracy')
plt.subplot(2, 1, 2)
plt.plot(train_losses, label='Training Loss')
plt.plot(test_losses, label='Validation Loss')
plt.legend(loc='upper right')
plt.ylabel('Binary Cross Entropy')
plt.title('Training and Validation Loss')
plt.xlabel('epoch')
plt.show()
plot_result(deep_history)