import gguf import numpy as np import torch import torch.nn as nn import torchvision.datasets as dsets import torchvision.transforms as transforms from torch.autograd import Variable import sys from time import time input_size = 784 # img_size = (28,28) ---> 28*28=784 in total hidden_size = 500 # number of nodes at hidden layer num_classes = 10 # number of output classes discrete range [0,9] num_epochs = 30 # number of times which the entire dataset is passed throughout the model batch_size = 1000 # the size of input data used for one iteration lr = 1e-3 # size of step class Net(nn.Module): def __init__(self, input_size, hidden_size, num_classes): super(Net, self).__init__() self.fc1 = nn.Linear(input_size, hidden_size) self.relu = nn.ReLU() self.fc2 = nn.Linear(hidden_size, num_classes) def forward(self, x): out = self.fc1(x) out = self.relu(out) out = self.fc2(out) return out def train(model_path): train_data = dsets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True) test_data = dsets.MNIST(root='./data', train=False, transform=transforms.ToTensor()) assert len(train_data) == 60000 assert len(test_data) == 10000 kwargs_train_test = dict(batch_size=batch_size, num_workers=4, pin_memory=True) train_gen = torch.utils.data.DataLoader(dataset=train_data, shuffle=True, **kwargs_train_test) test_gen = torch.utils.data.DataLoader(dataset=test_data, shuffle=False, **kwargs_train_test) net = Net(input_size, hidden_size, num_classes) if torch.cuda.is_available(): net.cuda() loss_function = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(net.parameters(), lr=lr) t_start = time() for epoch in range(num_epochs): loss_history = [] ncorrect = 0 for i, (images, labels) in enumerate(train_gen): images = Variable(images.view(-1, 28*28)) labels = Variable(labels) if torch.cuda.is_available(): images = images.cuda() labels = labels.cuda() optimizer.zero_grad() outputs = net(images) loss = loss_function(outputs, labels) loss_history.append(loss.cpu().data) _, predictions = torch.max(outputs, 1) ncorrect += (predictions == labels).sum() loss.backward() optimizer.step() if (i + 1)*batch_size % 10000 == 0: loss_mean = np.mean(loss_history) accuracy = ncorrect / ((i + 1) * batch_size) print( f"Epoch [{epoch+1:02d}/{num_epochs}], " f"Step [{(i+1)*batch_size:05d}/{len(train_data)}], " f"Loss: {loss_mean:.4f}, Accuracy: {100*accuracy:.2f}%") print() print(f"Training took {time()-t_start:.2f}s") loss_history = [] ncorrect = 0 for i, (images, labels) in enumerate(test_gen): images = Variable(images.view(-1, 28*28)) labels = Variable(labels) if torch.cuda.is_available(): images = images.cuda() labels = labels.cuda() outputs = net(images) loss = loss_function(outputs, labels) loss_history.append(loss.cpu().data) _, predictions = torch.max(outputs, 1) ncorrect += (predictions == labels).sum().cpu().numpy() loss_mean = np.mean(loss_history) loss_uncertainty = np.std(loss_history) / np.sqrt(len(loss_history) - 1) accuracy_mean = ncorrect / (len(test_gen) * batch_size) accuracy_uncertainty = np.sqrt(accuracy_mean * (1.0 - accuracy_mean) / (len(test_gen) * batch_size)) print() print(f"Test loss: {loss_mean:.6f}+-{loss_uncertainty:.6f}, Test accuracy: {100*accuracy_mean:.2f}+-{100*accuracy_uncertainty:.2f}%") gguf_writer = gguf.GGUFWriter(model_path, "mnist-fc") print() print(f"Model tensors saved to {model_path}:") for tensor_name in net.state_dict().keys(): data = net.state_dict()[tensor_name].squeeze().cpu().numpy() print(tensor_name, "\t", data.shape) gguf_writer.add_tensor(tensor_name, data) gguf_writer.write_header_to_file() gguf_writer.write_kv_data_to_file() gguf_writer.write_tensors_to_file() gguf_writer.close() if __name__ == '__main__': if len(sys.argv) != 2: print(f"Usage: {sys.argv[0]} ") sys.exit(1) train(sys.argv[1])