import torch
|
|
import numpy as np
|
|
import matplotlib
|
|
#matplotlib.use('TkAgg')
|
|
from matplotlib import pyplot as plt
|
|
import cv2, os, sys
|
|
from torch.utils.data import Dataset
|
|
|
|
from torch.utils.data import ConcatDataset, DataLoader, Subset
|
|
import torch.nn as nn
|
|
import torchvision.transforms as transforms
|
|
from torchvision.datasets import DatasetFolder
|
|
from PIL import Image
|
|
from SimBinaryNetpytorch.models.binarized_modules import CimSimConv2d
|
|
from SimBinaryNetpytorch.models.binarized_modules import BinarizeConv2d, IdealCimConv2d
|
|
from BinaryNetpytorch.models.binarized_modules import BinarizeConv2d as BConv2d
|
|
from BinaryNetpytorch.models.binarized_modules import Binarize,HingeLoss
|
|
import seaborn as sns
|
|
import random
|
|
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
|
|
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
|
|
batch_size = 8
|
|
num_epoch = 150
|
|
LEARN_RATE = 0.001
|
|
|
|
seed = 333
|
|
torch.manual_seed(seed)
|
|
torch.cuda.manual_seed(seed)
|
|
torch.cuda.manual_seed_all(seed)
|
|
np.random.seed(seed)
|
|
random.seed(seed)
|
|
torch.backends.cudnn.benchmark = False
|
|
torch.backends.cudnn.deterministic = True
|
|
|
|
|
|
H = [32, 64, 128]
|
|
H = [16, 32, 64]
|
|
|
|
RANDOM_WEIGHT_PER_EPOCH = 10
|
|
RANDOM_RATE = 1
|
|
|
|
|
|
class Classifier(nn.Module):
|
|
def __init__(self):
|
|
super(Classifier, self).__init__()
|
|
conv = CimSimConv2d
|
|
conv2 = BConv2d
|
|
conv3 = IdealCimConv2d
|
|
conv3 = BinarizeConv2d
|
|
#conv = nn.Conv2d
|
|
|
|
self.cnn_layers1 = nn.Sequential(
|
|
|
|
#conv(in_channels=1, out_channels=128, kernel_size=7),
|
|
#nn.BatchNorm2d(128),
|
|
#nn.LeakyReLU(0.5),
|
|
#conv(in_channels=128, out_channels=64, kernel_size=3),
|
|
#nn.BatchNorm2d(64),
|
|
#nn.LeakyReLU(0.5),
|
|
|
|
#input_size(1,30,40)
|
|
conv(1, H[0], 3, 1), #output_size(16,66,66)
|
|
#nn.BatchNorm2d(128),
|
|
nn.LeakyReLU(0.5),
|
|
#nn.Dropout(0.2),
|
|
nn.MaxPool2d(kernel_size = 2), #output_size(16,33,33)
|
|
)
|
|
self.cnn_layers2 = nn.Sequential(
|
|
|
|
conv(H[0], H[1], 3, 1), #output_size(24,31,31)
|
|
#nn.BatchNorm2d(64),
|
|
nn.LeakyReLU(0.5),
|
|
#nn.Dropout(0.2),
|
|
nn.MaxPool2d(kernel_size = 2), #output_size(24,15,15)
|
|
)
|
|
|
|
self.cnn_layers3 = nn.Sequential(
|
|
|
|
conv(H[1], H[2], 3, 1), #output_size(32,13,13)
|
|
#nn.BatchNorm2d(32),
|
|
nn.LeakyReLU(0.5),
|
|
#nn.Dropout(0.2),
|
|
nn.MaxPool2d(kernel_size = 2), #ouput_size(32,6,6)
|
|
#nn.LogSoftmax(),
|
|
#BinarizeConv2d(H[2], 8, (3,2), 1) #ouput_size(4,2,3) without max :(32,24,34)
|
|
conv2(H[2], 8, (3,2), 1) #ouput_size(4,2,3) without max :(32,24,34)
|
|
#conv(32, 8, (2,1), 1) #ouput_size(4,2,3) without max :(32,24,34)
|
|
|
|
)
|
|
|
|
|
|
|
|
def forward(self, x):
|
|
#print(x)
|
|
#print("input",float(torch.min(x)),float(torch.max(x)))
|
|
x = self.cnn_layers1(x)
|
|
#print("layer1",float(torch.min(x)),float(torch.max(x)))
|
|
#print(x)
|
|
x = self.cnn_layers2(x)
|
|
#print("layer2",float(torch.min(x)),float(torch.max(x)))
|
|
x = self.cnn_layers3(x)
|
|
#print("layer3",float(torch.min(x)),float(torch.max(x)))
|
|
#print(x)
|
|
#x = x.flatten(1)
|
|
#x = self.fc_layers(x)
|
|
#print(x.shape)
|
|
x = x.view(x.size(0), -1)
|
|
#print(x.shape)
|
|
#x = nn.LogSoftmax(x)
|
|
#print(x)
|
|
|
|
return x
|
|
|
|
class Cls_Dataset(Dataset):
|
|
def __init__(self, input, target):
|
|
self.input = input
|
|
self.target = target
|
|
def __getitem__(self, index):
|
|
return self.input[index], self.target[index]
|
|
def __len__(self):
|
|
return len(self.input)
|
|
|
|
def Load_data(path, cls):
|
|
data = []
|
|
label = []
|
|
f = 0
|
|
for c in range(cls):
|
|
t = 0
|
|
img = []
|
|
data_path = path + "/0"+str(c)+"/"
|
|
for filename in os.listdir(data_path):
|
|
# with open(data_path + "/" + filename, "rb") as f_in:
|
|
|
|
tmp_input = cv2.imread(data_path + filename,cv2.IMREAD_UNCHANGED)
|
|
#print(tmp_input)
|
|
tmp_input = cv2.resize(tmp_input, (30,40), interpolation = cv2.INTER_AREA)
|
|
tmp_input = tmp_input.astype(int)
|
|
tmp_input = tmp_input//2
|
|
tmp_input = tmp_input - 63
|
|
tmp_input = np.where(tmp_input > 63, 63, tmp_input)
|
|
tmp_input = tmp_input[:, :, np.newaxis]
|
|
tmp_input = tmp_input.transpose(2,0,1)
|
|
|
|
|
|
|
|
|
|
if img is not None:
|
|
img.append(tmp_input)
|
|
else:
|
|
img = tmp_input
|
|
label_tmp = np.full((len(img),1),c)
|
|
|
|
if f != 0:
|
|
data = np.append(data,img,axis=0)
|
|
else:
|
|
data = img
|
|
if f != 0:
|
|
label = np.append(label,label_tmp,axis=0)
|
|
else:
|
|
label = label_tmp
|
|
f = 1
|
|
|
|
|
|
|
|
label = np.squeeze(label)
|
|
|
|
label = np.array(label)
|
|
#print(data)
|
|
data = np.array(data)
|
|
#print(label.shape)
|
|
data = data.astype('float32')
|
|
|
|
return data, label
|
|
|
|
def main():
|
|
# test_set = DatasetFolder("./dataset/8cls_srcnnimg/test", loader=lambda x: Image.open(x), extensions="jpg", transform=test_tfm)
|
|
# val_set = DatasetFolder("./dataset/8cls_srcnnimg/train", loader=lambda x: Image.open(x), extensions="jpg", transform=test_tfm)
|
|
global num_epoch
|
|
|
|
train_data, train_label = Load_data("./dataset/8cls_grideye/train",8)
|
|
train = Cls_Dataset(train_data, train_label)
|
|
train_loader = DataLoader(
|
|
train, batch_size=100, shuffle=True,
|
|
num_workers=4, pin_memory=True, drop_last=True
|
|
)
|
|
|
|
test_data, test_label = Load_data("./dataset/8cls_grideye/test",8)
|
|
|
|
test = Cls_Dataset(test_data, test_label)
|
|
|
|
test_loader = DataLoader(
|
|
test, batch_size=100, shuffle=True,
|
|
num_workers=4, pin_memory=True, drop_last=True
|
|
)
|
|
|
|
val_data, val_label = Load_data("./dataset/8cls_grideye/val",8)
|
|
|
|
val = Cls_Dataset(val_data, val_label)
|
|
|
|
val_loader = DataLoader(
|
|
val, batch_size=100, shuffle=True,
|
|
num_workers=4, pin_memory=True, drop_last=True
|
|
)
|
|
|
|
|
|
|
|
|
|
save_path = 'models.ckpt'
|
|
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
|
model = Classifier().to(device)
|
|
#optimizer = torch.optim.Adam(model.parameters(), lr=0.1)
|
|
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
|
|
try:
|
|
checkpoint = torch.load('training_state_pre.bin')
|
|
model.load_state_dict(checkpoint['state_dict'])
|
|
#optimizer.load_state_dict(checkpoint['optimizer'])
|
|
#model.load_state_dict(torch.load('models_pre.ckpt'))
|
|
num_epoch = 150
|
|
except:
|
|
print('cannot read from pretrained model.')
|
|
criterion = nn.CrossEntropyLoss()
|
|
best_accuracy = 0.0
|
|
last_save = 0
|
|
for epoch in range(num_epoch):
|
|
model.train()
|
|
running_loss = 0.0
|
|
total = 0
|
|
correct = 0
|
|
for i, data in enumerate(train_loader):
|
|
inputs, labels = data
|
|
inputs = inputs.to(device)
|
|
labels = labels.to(device)
|
|
optimizer.zero_grad()
|
|
|
|
outputs = model(inputs)
|
|
#print(outputs.shape)
|
|
|
|
loss = criterion(outputs, labels)
|
|
loss.backward()
|
|
#print(model)
|
|
#print(model.cnn_layers3[3].weight.grad)
|
|
|
|
|
|
for p in list(model.parameters()):
|
|
if hasattr(p,'org'):
|
|
p.data.copy_(p.org)
|
|
|
|
optimizer.step()
|
|
|
|
for p in list(model.parameters()):
|
|
if hasattr(p,'org'):
|
|
p.org.copy_(p.data.clamp_(-1,1))
|
|
|
|
running_loss += loss.item()
|
|
total += labels.size(0)
|
|
_,predicted = torch.max(outputs.data,1)
|
|
#print(predicted)
|
|
#print("label",labels)
|
|
correct += (predicted == labels).sum().item()
|
|
train_acc = correct / total
|
|
|
|
print(f"[ Train | {epoch + 1:03d}/{num_epoch:03d} ] loss = {running_loss:.5f}, acc = {train_acc:.5f}")
|
|
|
|
model.eval()
|
|
with torch.no_grad():
|
|
correct = 0
|
|
total = 0
|
|
for i, data in enumerate(val_loader):
|
|
inputs, labels = data
|
|
inputs = inputs.to(device)
|
|
labels = labels.to(device)
|
|
outputs = model(inputs)
|
|
_,predicted = torch.max(outputs.data,1)
|
|
total += labels.size(0)
|
|
correct += (predicted == labels).sum().item()
|
|
val_acc = correct / total
|
|
|
|
if val_acc > best_accuracy:
|
|
last_save = epoch
|
|
best_accuracy = val_acc
|
|
torch.save(model.state_dict(), save_path)
|
|
state = {'state_dict': model.state_dict(), 'optimizer': optimizer.state_dict()}
|
|
torch.save(state, 'training_state.bin')
|
|
print("Save Model")
|
|
|
|
print(f"[ Val | {epoch + 1:03d}/{num_epoch:03d} ] acc = {val_acc:.5f}")
|
|
|
|
|
|
model = Classifier().to(device)
|
|
model.load_state_dict(torch.load(save_path))
|
|
model.eval()
|
|
stat = np.zeros((8,8))
|
|
with torch.no_grad():
|
|
correct = 0
|
|
total = 0
|
|
print(model)
|
|
for i, data in enumerate(test_loader):
|
|
inputs, labels = data
|
|
inputs = inputs.to(device)
|
|
labels = labels.to(device)
|
|
outputs = model(inputs)
|
|
#print(outputs.data)
|
|
_,predicted = torch.max(outputs.data,1)
|
|
#print(predicted)
|
|
total += labels.size(0)
|
|
correct += (predicted == labels).sum().item()
|
|
#print(labels)
|
|
#print(outputs.size())
|
|
|
|
|
|
print('Test Accuracy:{} %'.format((correct / total) * 100))
|
|
print('Save at', last_save+1)
|
|
if __name__ == '__main__':
|
|
main()
|