Browse Source

Experiment with CNN model

DAGsHub-Official 1 year ago
parent
commit
310e107039
8 changed files with 89 additions and 32 deletions
  1. 4 4
      Dvcfile
  2. 11 4
      code/eval.py
  3. 21 0
      code/my_torch_model.py
  4. 46 17
      code/train_model.py
  5. 1 1
      metrics/eval.json
  6. 1 1
      metrics/train_metric.json
  7. 1 1
      requirements.txt
  8. 4 4
      training.dvc

+ 4 - 4
Dvcfile

@@ -2,14 +2,14 @@ cmd: ' python3 code/eval.py'
 deps:
 - md5: a5257a91e73920bdd4cafd0f88105b74
   path: data/processed_test_data.npy
-- md5: d72417286b48ba89f02d83ca3f9642d4
+- md5: 825566e95183dcd0bed1c86fb253d015
   path: data/model.pkl
-- md5: 75c6e9b5ffa5ab5bbf83b7c3e8de188d
+- md5: 4ea256db731376c4052b9be975d6087c
   path: code/eval.py
-md5: 15947884e1222de47c0ef1ba74bda690
+md5: 0f13a6bbe5d7e58c0af2fe741d1a90d6
 outs:
 - cache: false
-  md5: 42e05a4d1c5f16b21c304c269178b5a8
+  md5: cd7e4336d4f3dcc2ba925f5b46185f9a
   metric:
     type: json
     xpath: accuracy

+ 11 - 4
code/eval.py

@@ -4,7 +4,10 @@ Evaluate model performance
 import pickle
 import json
 import numpy as np
-from sklearn.metrics import accuracy_score, precision_score, recall_score, roc_auc_score
+from sklearn.metrics import accuracy_score
+
+
+import torch # New line
 
 
 def eval_model():
@@ -15,14 +18,19 @@ def eval_model():
     # Load trained model
     with open('./data/model.pkl', 'rb') as f:
         model = pickle.load(f)
+
+    # Switch model to evaluation (inference) mode
+    model.eval()
+
     print("done.")
+
     # Divide loaded data-set into data and labels
     labels = test_data[:, 0]
-    data = test_data[:, 1:]
+    data = torch.Tensor(test_data[:, 1:].reshape([test_data.shape[0], 1, 28, 28]))
 
     # Run model on test data
     print("Running model on test data...")
-    predictions = model.predict(data)
+    predictions = model(data).max(1, keepdim=True)[1].cpu().data.numpy()
     print("done.")
 
     # Calculate metric scores
@@ -37,4 +45,3 @@ def eval_model():
 
 if __name__ == '__main__':
     eval_model()
-

+ 21 - 0
code/my_torch_model.py

@@ -0,0 +1,21 @@
+import torch.nn as nn
+import torch.nn.functional as F
+
+class Net(nn.Module):
+    def __init__(self):
+        super(Net, self).__init__()
+        self.conv1 = nn.Conv2d(1, 20, 5, 1)
+        self.conv2 = nn.Conv2d(20, 50, 5, 1)
+        self.fc1 = nn.Linear(4*4*50, 500)
+        self.fc2 = nn.Linear(500, 10)
+
+    def forward(self, x):
+        x = F.relu(self.conv1(x))
+        x = F.max_pool2d(x, 2, 2)
+        x = F.relu(self.conv2(x))
+        x = F.max_pool2d(x, 2, 2)
+        x = x.view(-1, 4*4*50)
+        x = F.relu(self.fc1(x))
+        x = self.fc2(x)
+        return F.log_softmax(x, dim=1)
+

+ 46 - 17
code/train_model.py

@@ -4,38 +4,68 @@ Train classification model for MNIST
 import json
 import pickle
 import numpy as np
-from sklearn.svm import SVC
-from sklearn.multiclass import OneVsRestClassifier
 import time
 
+# New imports
+import torch
+import torch.utils.data
+import torch.nn.functional as F
+import torch.optim as optim
+
+from my_torch_model import Net
+
+# New function
+def train(model, device, train_loader, optimizer, epoch):
+    log_interval = 100
+    model.train()
+    for batch_idx, (data, target) in enumerate(train_loader):
+        data, target = data.to(device), target.to(device)
+        optimizer.zero_grad()
+        output = model(data)
+        loss = F.nll_loss(output, target)
+        loss.backward()
+        optimizer.step()
+        if batch_idx % log_interval == 0:
+            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
+                epoch, batch_idx * len(data), len(train_loader.dataset),
+                       100. * batch_idx / len(train_loader), loss.item()))
+
 
 def train_model():
     # Measure training time
     start_time = time.time()
 
+    # Setting up network
+    print("Setting up Params...")
+    device = torch.device("cpu")
+    batch_size = 64
+    epochs = 3
+    learning_rate = 0.01
+    momentum = 0.5
+    print("done.")
+
     # Load training data
     print("Load training data...")
     train_data = np.load('./data/processed_train_data.npy')
 
-    # Choose a random sample of images from the training data.
-    # This is important since SVM training time increases quadratically with the number of training samples.
-    print("Choosing smaller sample to shorten training time...")
-    # Set a random seed so that we get the same "random" choices when we try to recreate the experiment.
-    np.random.seed(42)
-
-    num_samples = 5000
-    choice = np.random.choice(train_data.shape[0], num_samples, replace=False)
-    train_data = train_data[choice, :]
-
     # Divide loaded data-set into data and labels
-    labels = train_data[:, 0]
-    data = train_data[:, 1:]
+    labels = torch.Tensor(train_data[:, 0]).long()
+    data = torch.Tensor(train_data[:, 1:].reshape([train_data.shape[0], 1, 28, 28]))
+    torch_train_data = torch.utils.data.TensorDataset(data, labels)
+    train_loader = torch.utils.data.DataLoader(torch_train_data,
+                                               batch_size=batch_size,
+                                               shuffle=True)
     print("done.")
 
     # Define SVM classifier and train model
     print("Training model...")
-    model = OneVsRestClassifier(SVC(kernel='linear'), n_jobs=6)
-    model.fit(data, labels)
+    model = Net().to(device)
+    optimizer = optim.SGD(model.parameters(),
+                          lr=learning_rate,
+                          momentum=momentum)
+
+    for epoch in range(1, epochs + 1):
+        train(model, device, train_loader, optimizer, epoch)
     print("done.")
 
     # Save model as pkl
@@ -54,4 +84,3 @@ def train_model():
 
 if __name__ == '__main__':
     train_model()
-

+ 1 - 1
metrics/eval.json

@@ -1 +1 @@
-{"accuracy": 0.8583}
+{"accuracy": 0.9845}

+ 1 - 1
metrics/train_metric.json

@@ -1 +1 @@
-{"training_time": 34.35910105705261}
+{"training_time": 150.54586172103882}

+ 1 - 1
requirements.txt

@@ -6,4 +6,4 @@ scikit-learn==0.20.2
 scipy==1.2.0
 six==1.12.0
 sklearn==0.0
-
+torch==1.0.0

+ 4 - 4
training.dvc

@@ -2,15 +2,15 @@ cmd: ' python3 code/train_model.py'
 deps:
 - md5: 9ee0468925c998fda26d197a14d1caec
   path: data/processed_train_data.npy
-- md5: 655c3242c17b3d0213d7ce4d9f78344d
+- md5: 5a582b93eea1f5f666e53dfb3edab32b
   path: code/train_model.py
-md5: 25b384cbe19f26b43bd3213176935147
+md5: 149c3c54df013ec8c750904e3286a8b4
 outs:
 - cache: true
-  md5: d72417286b48ba89f02d83ca3f9642d4
+  md5: 825566e95183dcd0bed1c86fb253d015
   path: data/model.pkl
 - cache: false
-  md5: 6ac2c7dcd46f94ebfc9546a81c0eb0be
+  md5: fbdc61420600a6927724ee94bc4b677d
   metric:
     type: json
     xpath: training_time