forked from Silectio/Projet-Computer-Vision
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVGG16-autoencoder.py
113 lines (102 loc) · 3.96 KB
/
VGG16-autoencoder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.models as models
import torchvision.transforms as transforms
from loadDataset import get_dataloaders
from PIL import ImageFile
from tqdm import tqdm
ImageFile.LOAD_TRUNCATED_IMAGES = True
class VGG16Encoder(nn.Module):
def __init__(self):
super(VGG16Encoder, self).__init__()
vgg16 = models.vgg16(pretrained=True)
self.features = nn.Sequential(*list(vgg16.features.children())[:16])
def forward(self, x):
return self.features(x)
class Decoder(nn.Module):
def __init__(self):
super(Decoder, self).__init__()
self.decoder = nn.Sequential(
nn.ConvTranspose2d(256, 128, 3, 2, 1, 1),
nn.ReLU(inplace=True),
nn.ConvTranspose2d(128, 64, 3, 2, 1, 1),
nn.ReLU(inplace=True),
nn.ConvTranspose2d(64, 3, 3, 1, 1)
)
def forward(self, x):
return self.decoder(x)
class Autoencoder(nn.Module):
def __init__(self):
super(Autoencoder, self).__init__()
self.encoder = VGG16Encoder()
self.decoder = Decoder()
def forward(self, x):
latent = self.encoder(x)
reconstruction = self.decoder(latent)
return reconstruction
def train(train_loader, model,device):
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=1e-4)
model.train()
for epoch in range(5):
total_loss = 0
for images, _ in tqdm(train_loader):
images = images.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, images)
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch {epoch + 1}, Loss: {total_loss / len(train_loader)}")
if __name__ == '__main__':
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor()
])
train_loader, valid_loader, test_loader = get_dataloaders(transform=transform, batch_size=32)
model = Autoencoder().to(device)
#on affiche la taille du latent space
for images, _ in train_loader:
latentSize = Autoencoder().encoder(images).shape
print(latentSize)
break
train(train_loader, model, device)
torch.save(model.state_dict(), 'models/VGG16-Autoencoder_autoencoder.pth')
model.encoder.load_state_dict(torch.load('models/VGG16-Autoencoder_autoencoder.pth'))
# CLASSIFIER ===
class Classifier(nn.Module):
def __init__(self, encoder):
super(Classifier, self).__init__()
self.encoder = encoder
for param in self.encoder.parameters():
param.requires_grad = False
self.fc = nn.Linear(256 * 14 * 14, 2)
def forward(self, x):
with torch.no_grad():
x = self.encoder(x)
x = x.view(x.size(0), -1)
x = self.fc(x)
return x
def train_classifier(valid_loader, model, device):
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.fc.parameters(), lr=1e-4)
model.train()
for epoch in range(5):
total_loss = 0
for images, labels in tqdm(valid_loader):
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch {epoch + 1}, Loss: {total_loss / len(valid_loader)}")
# Assuming valid_loader has labels for classification
classifier = Classifier(model.encoder).to(device)
train_classifier(valid_loader, classifier, device)
#on sauvegarde le modèle
torch.save(classifier.state_dict(), 'models/VGG16-Autoencoder_classifier.pth')