1
+ # This code is used in the 'Run MATLAB from Python' example
2
+
3
+ # Copyright 2019-2021 The MathWorks, Inc.
4
+
5
+ import torch
6
+ from torch .utils .data import Dataset , DataLoader
7
+ import torch .nn as nn
8
+ import torch .onnx
9
+
10
+ import time
11
+ import os
12
+
13
+ cudaAvailable = torch .cuda .is_available ()
14
+ if cudaAvailable :
15
+ cuda = torch .device ('cuda' )
16
+
17
+ # start a MATLAB engine
18
+ import matlab .engine
19
+ MLEngine = matlab .engine .start_matlab ()
20
+
21
+ miniBatchSize = 128.0
22
+
23
+ # Prepare training dataset
24
+ class TrainData (Dataset ):
25
+ def __init__ (self ):
26
+ # Create persistent training dataset in MATLAB
27
+ MLEngine .setupDatasets (miniBatchSize )
28
+ # Set the dataset length to the number of minibatches
29
+ # in the training dataset
30
+ self .len = int (MLEngine .getNumIterationsPerEpoch ())
31
+
32
+ def __getitem__ (self , index ):
33
+ # Call MATLAB to get a minibatch of features + labels
34
+ minibatch = MLEngine .extractTrainingFeatures ()
35
+ x = torch .FloatTensor (minibatch .get ('features' ))
36
+ y = torch .FloatTensor (minibatch .get ('labels' ))
37
+ return x , y
38
+
39
+ def __len__ (self ):
40
+ return int (self .len )
41
+
42
+ print ('Setting up datastores...' )
43
+ trainDataset = TrainData ()
44
+ print ('Datastore setup complete' )
45
+ print ('Minibatch size: ' , int (miniBatchSize ))
46
+ print ('Number of training files: ' , int (trainDataset .len * miniBatchSize ))
47
+ print ('Number of minibatches per epoch: ' , int (trainDataset .len ))
48
+
49
+ trainLoader = DataLoader (dataset = trainDataset , batch_size = 1 )
50
+
51
+ print ('Computing validation features...' )
52
+ # Prepare validation dataset
53
+ # Call MATLAB to compute validation features
54
+ valFeatures = MLEngine .extractValidationFeatures ()
55
+ XValidation = valFeatures ["features" ]
56
+ YValidation = valFeatures ["labels" ]
57
+
58
+ # Create Data Class
59
+ class ValData (Dataset ):
60
+ # Constructor
61
+ def __init__ (self ):
62
+ self .x = XValidation
63
+ self .y = YValidation
64
+ self .len = self .y .size [0 ]
65
+
66
+ # Getter
67
+ def __getitem__ (self , index ):
68
+ x = torch .FloatTensor (self .x [index ])
69
+ y = torch .FloatTensor (self .y [index ])
70
+ return x , y
71
+
72
+ # Get Length
73
+ def __len__ (self ):
74
+ return self .len
75
+
76
+ valDataset = ValData ()
77
+ valLoader = DataLoader (dataset = valDataset , batch_size = valDataset .len )
78
+ print ('Validation feature computation complete' )
79
+
80
+ # Create the neural network
81
+ NumF = 12
82
+ numHops = 98
83
+ timePoolSize = 13
84
+ dropoutProb = 0.2
85
+ numClasses = 11
86
+
87
+ class CNN (nn .Module ):
88
+
89
+ # Contructor
90
+ def __init__ (self , out_1 = NumF ):
91
+ super (CNN , self ).__init__ ()
92
+ self .cnn1 = nn .Conv2d (in_channels = 1 , out_channels = out_1 , kernel_size = 3 , padding = 1 )
93
+ self .batch1 = nn .BatchNorm2d (out_1 )
94
+ self .relu1 = nn .ReLU ()
95
+
96
+ self .maxpool1 = nn .MaxPool2d (kernel_size = 3 , stride = 2 , padding = 1 )
97
+
98
+ self .cnn2 = nn .Conv2d (in_channels = out_1 , out_channels = 2 * out_1 , kernel_size = 3 , padding = 1 )
99
+ self .batch2 = nn .BatchNorm2d (2 * out_1 )
100
+ self .relu2 = nn .ReLU ()
101
+
102
+ self .maxpool2 = nn .MaxPool2d (kernel_size = 3 , stride = 2 , padding = 1 )
103
+
104
+ self .cnn3 = nn .Conv2d (in_channels = 2 * out_1 , out_channels = 4 * out_1 , kernel_size = 3 , padding = 1 )
105
+ self .batch3 = nn .BatchNorm2d (4 * out_1 )
106
+ self .relu3 = nn .ReLU ()
107
+
108
+ self .maxpool3 = nn .MaxPool2d (kernel_size = 3 , stride = 2 , padding = 1 )
109
+
110
+ self .cnn4 = nn .Conv2d (in_channels = 4 * out_1 , out_channels = 4 * out_1 , kernel_size = 3 , padding = 1 )
111
+ self .batch4 = nn .BatchNorm2d (4 * out_1 )
112
+ self .relu4 = nn .ReLU ()
113
+ self .cnn5 = nn .Conv2d (in_channels = 4 * out_1 , out_channels = 4 * out_1 , kernel_size = 3 , padding = 1 )
114
+ self .batch5 = nn .BatchNorm2d (4 * out_1 )
115
+ self .relu5 = nn .ReLU ()
116
+
117
+ self .maxpool4 = nn .MaxPool2d (kernel_size = (timePoolSize , 1 ))
118
+
119
+ self .dropout = nn .Dropout2d (dropoutProb )
120
+
121
+ self .fc = nn .Linear (336 , numClasses )
122
+
123
+ #self.softmax = nn.Softmax(dim = 1)
124
+
125
+ # Prediction
126
+ def forward (self , x ):
127
+ out = self .cnn1 (x )
128
+ out = self .batch1 (out )
129
+ out = self .relu1 (out )
130
+
131
+ out = self .maxpool1 (out )
132
+
133
+ out = self .cnn2 (out )
134
+ out = self .batch2 (out )
135
+ out = self .relu2 (out )
136
+
137
+ out = self .maxpool2 (out )
138
+
139
+ out = self .cnn3 (out )
140
+ out = self .batch3 (out )
141
+ out = self .relu3 (out )
142
+
143
+ out = self .maxpool3 (out )
144
+
145
+ out = self .cnn4 (out )
146
+ out = self .batch4 (out )
147
+ out = self .relu4 (out )
148
+ out = self .cnn5 (out )
149
+ out = self .batch5 (out )
150
+ out = self .relu5 (out )
151
+
152
+ out = self .maxpool4 (out )
153
+
154
+ out = self .dropout (out )
155
+
156
+ out = out .view (out .size (0 ), - 1 )
157
+ out = self .fc (out )
158
+ #out = self.softmax(out)
159
+
160
+ return out
161
+
162
+ model = CNN ()
163
+ if cudaAvailable :
164
+ model .cuda ()
165
+
166
+ # Define training parameters
167
+ n_epochs = 25
168
+ criterion = nn .CrossEntropyLoss ()
169
+ learning_rate = 3e-4
170
+ optimizer = torch .optim .Adam (model .parameters (), lr = learning_rate )
171
+ loss_list = []
172
+ accuracy_list = []
173
+ numValItems = len (valDataset )
174
+
175
+ doValidation = True
176
+
177
+ print ('Training...' )
178
+
179
+ for epoch in range (n_epochs ):
180
+
181
+ if epoch == 20 :
182
+ for g in optimizer .param_groups :
183
+ g ['lr' ] = 3e-5
184
+
185
+ count = 0
186
+ for batch in trainLoader :
187
+ count += 1
188
+ print ('Epoch ' , epoch + 1 , ' Iteration' , count , ' of ' , trainDataset .len )
189
+ if cudaAvailable :
190
+ x = batch [0 ].cuda ()
191
+ y = batch [1 ].cuda ()
192
+ else :
193
+ x = batch [0 ]
194
+ y = batch [1 ]
195
+ optimizer .zero_grad ()
196
+ z = model (torch .squeeze (x .float (), 0 ))
197
+ loss = criterion (z , torch .squeeze (y ).long ())
198
+ loss .backward ()
199
+ optimizer .step ()
200
+
201
+ if doValidation :
202
+ correct = 0
203
+ # perform a prediction on the validation data
204
+ for x_test , y_test in valLoader :
205
+ if cudaAvailable :
206
+ x_test = x_test .cuda ()
207
+ y_test = y_test .cuda ()
208
+ else :
209
+ x_test = x_test
210
+ y_test = y_test
211
+ z = model (x_test .float ())
212
+ _ , yhat = torch .max (z .data , 1 )
213
+ correct += (yhat == y_test .squeeze ()).sum ().item ()
214
+ accuracy = correct / numValItems
215
+ print ('Validation accuracy: ' , accuracy )
216
+ accuracy_list .append (accuracy )
217
+ loss_list .append (loss .data )
218
+
219
+ # Export the trained model to ONXX format
220
+ if cudaAvailable :
221
+ x = torch .empty (1 , 1 , 98 , 50 ).cuda ()
222
+ else :
223
+ x = torch .empty (1 , 1 , 98 , 50 )
224
+
225
+ torch .onnx .export (model ,
226
+ x ,
227
+ "cmdRecognition.onnx" ,
228
+ export_params = True ,
229
+ opset_version = 9 ,
230
+ do_constant_folding = True ,
231
+ input_names = ['input' ],
232
+ output_names = ['output' ])
233
+
234
+ print ('Training complete' )
0 commit comments