|
3 | 3 | import torchvision
|
4 | 4 | import torchvision.transforms as transforms
|
5 | 5 | import matplotlib.pyplot as plt
|
| 6 | +import ssl |
6 | 7 |
|
7 |
| -# Device configuration |
8 |
| -device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') |
| 8 | +ssl._create_default_https_context = ssl._create_unverified_context |
| 9 | + |
| 10 | +# GPU device configuration |
| 11 | +if torch.cuda.is_available(): |
| 12 | + device = torch.device('cuda') |
| 13 | + print('Using GPU') |
| 14 | +elif torch.backends.mps.is_available(): |
| 15 | + device = torch.device('mps') |
| 16 | + print('Using MPS') |
| 17 | +else: |
| 18 | + device = torch.device('cpu') |
| 19 | + print('Using CPU') |
9 | 20 |
|
10 | 21 | # Hyper-parameters
|
11 | 22 | input_size = 784 # 28x28
|
12 | 23 | hidden_size = 500
|
13 | 24 | num_classes = 10
|
14 |
| -num_epochs = 2 |
| 25 | +num_epochs = 10 |
15 | 26 | batch_size = 100
|
16 | 27 | learning_rate = 0.001
|
17 | 28 |
|
|
40 | 51 | for i in range(6):
|
41 | 52 | plt.subplot(2,3,i+1)
|
42 | 53 | plt.imshow(example_data[i][0], cmap='gray')
|
43 |
| -plt.show() |
| 54 | +# plt.show() |
44 | 55 |
|
45 | 56 | # Fully connected neural network with one hidden layer
|
46 | 57 | class NeuralNet(nn.Module):
|
47 |
| - def __init__(self, input_size, hidden_size, num_classes): |
48 |
| - super(NeuralNet, self).__init__() |
49 |
| - self.input_size = input_size |
50 |
| - self.l1 = nn.Linear(input_size, hidden_size) |
51 |
| - self.relu = nn.ReLU() |
52 |
| - self.l2 = nn.Linear(hidden_size, num_classes) |
53 |
| - |
54 |
| - def forward(self, x): |
55 |
| - out = self.l1(x) |
56 |
| - out = self.relu(out) |
57 |
| - out = self.l2(out) |
58 |
| - # no activation and no softmax at the end |
59 |
| - return out |
| 58 | + def __init__(self, input_size, hidden_size, num_classes): |
| 59 | + super(NeuralNet, self).__init__() |
| 60 | + self.input_size = input_size |
| 61 | + self.l1 = nn.Linear(input_size, hidden_size) |
| 62 | + self.relu = nn.ReLU() |
| 63 | + self.l2 = nn.Linear(hidden_size, hidden_size) |
| 64 | + def forward(self, x): |
| 65 | + out = self.l1(x) |
| 66 | + out = self.relu(out) |
| 67 | + out = self.l2(out) |
| 68 | + # no activation and no softmax at the end |
| 69 | + return out |
60 | 70 |
|
61 | 71 | model = NeuralNet(input_size, hidden_size, num_classes).to(device)
|
| 72 | +print(model) |
62 | 73 |
|
63 | 74 | # Loss and optimizer
|
64 | 75 | criterion = nn.CrossEntropyLoss()
|
65 |
| -optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) |
| 76 | +optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) |
66 | 77 |
|
67 | 78 | # Train the model
|
68 | 79 | n_total_steps = len(train_loader)
|
| 80 | +loss_list = [] |
| 81 | + |
69 | 82 | for epoch in range(num_epochs):
|
70 |
| - for i, (images, labels) in enumerate(train_loader): |
71 |
| - # origin shape: [100, 1, 28, 28] |
72 |
| - # resized: [100, 784] |
73 |
| - images = images.reshape(-1, 28*28).to(device) |
74 |
| - labels = labels.to(device) |
75 |
| - |
76 |
| - # Forward pass |
77 |
| - outputs = model(images) |
78 |
| - loss = criterion(outputs, labels) |
79 |
| - |
80 |
| - # Backward and optimize |
81 |
| - optimizer.zero_grad() |
82 |
| - loss.backward() |
83 |
| - optimizer.step() |
84 |
| - |
85 |
| - if (i+1) % 100 == 0: |
86 |
| - print (f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{n_total_steps}], Loss: {loss.item():.4f}') |
| 83 | + epoch_loss = 0 |
| 84 | + for i, (images, labels) in enumerate(train_loader): |
| 85 | + # origin shape: [100, 1, 28, 28] |
| 86 | + # resized: [100, 784] |
| 87 | + images = images.reshape(-1, 28*28).to(device) |
| 88 | + labels = labels.to(device) |
| 89 | + |
| 90 | + # Forward pass |
| 91 | + outputs = model(images) |
| 92 | + loss = criterion(outputs, labels) |
| 93 | + |
| 94 | + # Backward and optimize |
| 95 | + optimizer.zero_grad() |
| 96 | + loss.backward() |
| 97 | + optimizer.step() |
| 98 | + |
| 99 | + epoch_loss += loss.item() |
| 100 | + |
| 101 | + if (i+1) % 200 == 0: |
| 102 | + print (f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{n_total_steps}], Loss: {loss.item():.4f}') |
| 103 | + |
| 104 | + avg_epoch_loss = epoch_loss / n_total_steps |
| 105 | + loss_list.append(avg_epoch_loss) |
| 106 | + |
| 107 | +# Plot loss as a function of epoch |
| 108 | +plt.figure() |
| 109 | +plt.plot(range(1, num_epochs + 1), loss_list, label='Training Loss') |
| 110 | +plt.xlabel('Epoch') |
| 111 | +plt.ylabel('Loss') |
| 112 | +plt.title('Training Loss vs. Epoch') |
| 113 | +plt.legend() |
| 114 | +plt.show() |
87 | 115 |
|
88 | 116 | # Test the model
|
89 | 117 | # In test phase, we don't need to compute gradients (for memory efficiency)
|
90 | 118 | with torch.no_grad():
|
91 |
| - n_correct = 0 |
92 |
| - n_samples = 0 |
93 |
| - for images, labels in test_loader: |
94 |
| - images = images.reshape(-1, 28*28).to(device) |
95 |
| - labels = labels.to(device) |
96 |
| - outputs = model(images) |
97 |
| - # max returns (value ,index) |
98 |
| - _, predicted = torch.max(outputs.data, 1) |
99 |
| - n_samples += labels.size(0) |
100 |
| - n_correct += (predicted == labels).sum().item() |
101 |
| - |
102 |
| - acc = 100.0 * n_correct / n_samples |
103 |
| - print(f'Accuracy of the network on the 10000 test images: {acc} %') |
| 119 | + n_correct = 0 |
| 120 | + n_samples = 0 |
| 121 | + for images, labels in test_loader: |
| 122 | + images = images.reshape(-1, 28*28).to(device) |
| 123 | + labels = labels.to(device) |
| 124 | + outputs = model(images) |
| 125 | + # max returns (value ,index) |
| 126 | + _, predicted = torch.max(outputs.data, 1) |
| 127 | + n_samples += labels.size(0) |
| 128 | + n_correct += (predicted == labels).sum().item() |
| 129 | + |
| 130 | + acc = 100.0 * n_correct / n_samples |
| 131 | + print(f'Accuracy of the network on the 10000 test images: {acc} %') |
0 commit comments