forked from christophschuhmann/improved-aesthetic-predictor
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtrain_predictor.py
159 lines (116 loc) · 5.64 KB
/
train_predictor.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import os
# os.environ['CUDA_VISIBLE_DEVICES'] = "0" # in case you are using a multi GPU workstation, choose your GPU here
import tqdm
import pytorch_lightning as pl
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
import torch.nn.functional as F
import pandas as pd
from datasets import load_dataset
from torch.utils.data import TensorDataset, DataLoader
from MLP import MLP
import click
import numpy as np
@click.command()
@click.option('--epoch', help='Number of Epochs', type=int, required=True)
@click.option('--out', help='Output file of model', type=str, required=True)
@click.option('--learning-rate', help='Learning Rate', type=float, default=0.001)
@click.option('--val-percent', help='Percent of embeddings to use for validation', type=float, default=0.05)
@click.option('--batch-size', help='Batch size', type=int, default=256)
@click.option('--num-workers', help='Number of workers', type=int, default=16)
@click.option('--embedding-file', help='Name of embeddings file', type=str, default='embeddings/x_embeddings.npy')
@click.option('--score-file', help='Name of score file', type=str, default='embeddings/y_ratings.npy')
@click.option('--device', help='Torch device type (default uses cuda if avaliable)', type=str, default='default', show_default=True)
@click.option('--out', help='Output directory', metavar='DIR', type=str, default='embeddings')
class dotdict(dict):
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
# load the training data
def main(**kwargs):
opts = dotdict(kwargs)
x = np.load (opts.embedding_file)
y = np.load (opts.score_file)
val_percentage = opts.val_percent
train_border = int(x.shape()[0] * (1 - val_percentage) )
train_tensor_x = torch.Tensor(x[:train_border]) # transform to torch tensor
train_tensor_y = torch.Tensor(y[:train_border])
train_dataset = TensorDataset(train_tensor_x,train_tensor_y) # create your datset
train_loader = DataLoader(train_dataset, batch_size=opts.batch_size, shuffle=True, num_workers=opts.num_workers) # create your dataloader
val_tensor_x = torch.Tensor(x[train_border:]) # transform to torch tensor
val_tensor_y = torch.Tensor(y[train_border:])
'''
print(train_tensor_x.size())
print(val_tensor_x.size())
print( val_tensor_x.dtype)
print( val_tensor_x[0].dtype)
'''
val_dataset = TensorDataset(val_tensor_x,val_tensor_y) # create your datset
val_loader = DataLoader(val_dataset, batch_size=512, num_workers=16) # create your dataloader
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
if opts.device != 'default':
device = opts.device
model = MLP(768,x,y).to(device) # CLIP embedding dim is 768 for CLIP ViT L 14
model.lr = opts.learning_rate
optimizer = torch.optim.Adam(model.parameters())
# choose the loss you want to optimze for
criterion = nn.MSELoss()
criterion2 = nn.L1Loss()
epochs = opts.batch_size
model.train()
best_loss =999
save_name = opts.out
for epoch in range(epochs):
losses = []
losses2 = []
for batch_num, input_data in enumerate(train_loader):
optimizer.zero_grad()
x, y = input_data
x = x.to(device).float()
y = y.to(device)
output = model(x)
loss = criterion(output, y)
loss.backward()
losses.append(loss.item())
optimizer.step()
if batch_num % 1000 == 0:
print('\tEpoch %d | Batch %d | Loss %6.2f' % (epoch, batch_num, loss.item()))
#print(y)
print('Epoch %d | Loss %6.2f' % (epoch, sum(losses)/len(losses)))
losses = []
losses2 = []
for batch_num, input_data in enumerate(val_loader):
optimizer.zero_grad()
x, y = input_data
x = x.to(device).float()
y = y.to(device)
output = model(x)
loss = criterion(output, y)
lossMAE = criterion2(output, y)
#loss.backward()
losses.append(loss.item())
losses2.append(lossMAE.item())
#optimizer.step()
if batch_num % 1000 == 0:
print('\tValidation - Epoch %d | Batch %d | MSE Loss %6.2f' % (epoch, batch_num, loss.item()))
print('\tValidation - Epoch %d | Batch %d | MAE Loss %6.2f' % (epoch, batch_num, lossMAE.item()))
#print(y)
print('Validation - Epoch %d | MSE Loss %6.2f' % (epoch, sum(losses)/len(losses)))
print('Validation - Epoch %d | MAE Loss %6.2f' % (epoch, sum(losses2)/len(losses2)))
if sum(losses)/len(losses) < best_loss:
print("Best MAE Val loss so far. Saving model")
best_loss = sum(losses)/len(losses)
print( best_loss )
torch.save(model.state_dict(), save_name )
torch.save(model.state_dict(), save_name)
print( best_loss )
print("training done")
# inferece test with dummy samples from the val set, sanity check
print( "inferece test with dummy samples from the val set, sanity check")
model.eval()
output = model(x[:5].to(device))
print(output.size())
print(output)
if __name__ == "__main__":
main()