getting_started_no_avalanche.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. ################################################################################
  2. # Copyright (c) 2021 ContinualAI. #
  3. # Copyrights licensed under the MIT License. #
  4. # See the accompanying LICENSE file for terms. #
  5. # #
  6. # Date: 20-11-2020 #
  7. # Author(s): Vincenzo Lomonaco #
  8. # E-mail: contact@continualai.org #
  9. # Website: avalanche.continualai.org #
  10. ################################################################################
  11. """
  12. This is the getting started example, without the use of the Avalanche framework.
  13. This is useful to understand why Avalanche is such a wonderful tool.
  14. """
  15. from __future__ import absolute_import
  16. from __future__ import division
  17. from __future__ import print_function
  18. from os.path import expanduser
  19. import argparse
  20. import torch
  21. import torch.nn as nn
  22. from torch.nn import CrossEntropyLoss
  23. from torch.optim import SGD
  24. from torchvision import transforms
  25. from torchvision.datasets import MNIST
  26. from torchvision.transforms import ToTensor
  27. from torch.utils.data import DataLoader
  28. import numpy as np
  29. def main(args):
  30. # Config
  31. device = torch.device(f"cuda:{args.cuda}"
  32. if torch.cuda.is_available() and
  33. args.cuda >= 0 else "cpu")
  34. # model
  35. class SimpleMLP(nn.Module):
  36. def __init__(self, num_classes=10, input_size=28 * 28):
  37. super(SimpleMLP, self).__init__()
  38. self.features = nn.Sequential(
  39. nn.Linear(input_size, 512),
  40. nn.ReLU(inplace=True),
  41. nn.Dropout(),
  42. )
  43. self.classifier = nn.Linear(512, num_classes)
  44. self._input_size = input_size
  45. def forward(self, x):
  46. x = x.contiguous()
  47. x = x.view(x.size(0), self._input_size)
  48. x = self.features(x)
  49. x = self.classifier(x)
  50. return x
  51. model = SimpleMLP(num_classes=10)
  52. # CL Benchmark Creation
  53. print("Creating the benchmark...")
  54. list_train_dataset = []
  55. list_test_dataset = []
  56. rng_permute = np.random.RandomState(0)
  57. train_transform = transforms.Compose([
  58. ToTensor(),
  59. transforms.Normalize((0.1307,), (0.3081,))
  60. ])
  61. test_transform = transforms.Compose([
  62. ToTensor(),
  63. transforms.Normalize((0.1307,), (0.3081,))
  64. ])
  65. # for every incremental experience
  66. idx_permutations = []
  67. for i in range(2):
  68. idx_permutations.append(torch.from_numpy(
  69. rng_permute.permutation(784)).type(torch.int64))
  70. # add the permutation to the default dataset transformation
  71. train_transform_list = train_transform.transforms.copy()
  72. train_transform_list.append(
  73. transforms.Lambda(
  74. lambda x, i=i: x.view(-1)[idx_permutations[i]].view(1, 28, 28))
  75. )
  76. new_train_transform = transforms.Compose(train_transform_list)
  77. test_transform_list = test_transform.transforms.copy()
  78. test_transform_list.append(
  79. transforms.Lambda(
  80. lambda x, i=i: x.view(-1)[idx_permutations[i]].view(1, 28, 28))
  81. )
  82. new_test_transform = transforms.Compose(test_transform_list)
  83. # get the datasets with the constructed transformation
  84. permuted_train = MNIST(root=expanduser("~") + "/.avalanche/data/mnist/",
  85. train=True,
  86. download=True, transform=new_train_transform)
  87. permuted_test = MNIST(root=expanduser("~") + "/.avalanche/data/mnist/",
  88. train=False,
  89. download=True, transform=new_test_transform)
  90. list_train_dataset.append(permuted_train)
  91. list_test_dataset.append(permuted_test)
  92. # Train
  93. optimizer = SGD(model.parameters(), lr=0.001, momentum=0.9)
  94. criterion = CrossEntropyLoss()
  95. model.to(device)
  96. print("Starting training...")
  97. for task_id, train_dataset in enumerate(list_train_dataset):
  98. print("Starting task:", task_id)
  99. train_data_loader = DataLoader(
  100. train_dataset, batch_size=32, shuffle=False)
  101. for ep in range(1):
  102. print("Epoch: ", ep)
  103. for iteration, (train_mb_x, train_mb_y) in enumerate(
  104. train_data_loader):
  105. optimizer.zero_grad()
  106. train_mb_x = train_mb_x.to(device)
  107. train_mb_y = train_mb_y.to(device)
  108. # Forward
  109. logits = model(train_mb_x)
  110. # Loss
  111. loss = criterion(logits, train_mb_y)
  112. if iteration % 100 == 0:
  113. print("Iter: {}, Loss: {}".format(iteration, loss.item()))
  114. # Backward
  115. loss.backward()
  116. # Update
  117. optimizer.step()
  118. # Test
  119. acc_results = []
  120. print("Starting testing...")
  121. for task_id, test_dataset in enumerate(list_test_dataset):
  122. test_data_loader = DataLoader(
  123. test_dataset, batch_size=32)
  124. correct = 0
  125. for iteration, (test_mb_x, test_mb_y) in enumerate(
  126. test_data_loader):
  127. # Move mini-batch data to device
  128. test_mb_x = test_mb_x.to(device)
  129. test_mb_y = test_mb_y.to(device)
  130. # Forward
  131. test_logits = model(test_mb_x)
  132. preds = torch.argmax(test_logits.long(), dim=1)
  133. # compute acc
  134. correct += (test_mb_y.eq(preds)).sum().item()
  135. print("Task:", task_id)
  136. acc = (correct / len(test_dataset)) * 100
  137. print("Accuracy results: ", acc)
  138. acc_results.append(acc)
  139. if __name__ == '__main__':
  140. parser = argparse.ArgumentParser()
  141. parser.add_argument('--cuda', type=int, default=0,
  142. help='Select zero-indexed cuda device. -1 to use CPU.')
  143. args = parser.parse_args()
  144. main(args)