<jupyter_start><jupyter_text>Data Loading & Preprocessing:     1. Loading the dataset and Transform into Tensors:<jupyter_code>from torchvision import datasets, transforms
dataset_path=datasets.ImageFolder(root='fruits360/Training/', transform=transforms.Compose([transforms.ToTensor()]))<jupyter_output><empty_output><jupyter_text>2. Spliting the dataset Into Train and Test:            Spliting the Dataset into 80% training and 20% testing dataset, and shuffling the dataset to distribute the train         and test into random examples<jupyter_code>from torch.utils.data.sampler import SubsetRandomSampler

split = int(0.8 * len(dataset_path))
index_list = list(range(len(dataset_path)))
np.random.shuffle(index_list)
train_idx, test_idx = index_list[:split], index_list[split:] ## Traing and testing indexes.


## create sampler objects using SubsetRandomSampler
tr_sampler = SubsetRandomSampler(train_idx)
test_sampler = SubsetRandomSampler(test_idx)
## create iterator objects for train and test datasets
train_loader = torch.utils.data.DataLoader(dataset_path, batch_size=256, sampler=tr_sampler)
test_loader = torch.utils.data.DataLoader(dataset_path, batch_size=256, sampler=test_sampler)

print ("Total Number of Examples: ",len(dataset_path))
print ("Number of training Examples: ",len(tr_sampler))
print ("Number of testing Examples: ",len(test_sampler))
Classes_num=len(train_loader.dataset.classes)
print ('Number of Classes',Classes_num)
print('Classes Name: ', train_loader.dataset.classes)
print ('Example: ')
i1, l1 = next(iter(train_loader))
plt.title(train_loader.dataset.classes[l1[0]])
plt.imshow(np.array(i1[0].permute(1, 2, 0)));<jupyter_output>Example:<jupyter_text>Convolutional Neural Network The network has the following layout,    Input > Conv_Layer (ReLU) > MaxPool > Conv_Layer (ReLU) > MaxPool > Conv_Layer (ReLU) > MaxPool > FC (ReLU) > FC (ReLU) > FC (SoftMax) > 15 outputs        where:        Conv_Layer is a convolutional layer, ReLU is the activation function, MaxPool is a pooling layer, FC is a fully        connected layer and SoftMax is the activation function of the output layer.  Layer DimensionsBelow formula shown to check the size of layer by given parameters.![Conv layer formula for output size calculation](conv_layer_formula.png) Input Size        The images are 3x100x100, i.e., 3 channels (red, green, blue) each of size 100x100 pixels. First Convolutional Layer        The first convolutional layer expects 3 input channels and will convolve 6 filters each of size 3x9x9. Since padding    is set to 0 and stride is set to 1, the output size is 6x92x92, because                                                             (100−9)+1=92.     First Max-Pooling Layer        The first down-sampling layer uses max pooling with a 2x2 kernel and stride set to 2. This effectively drops the size     from 6x92x92 to 6x46x46. Second Convolutional Layer        The second convolutional layers expects 6 input channels and will convolve 8 filters each of size 6x7x7. Since     padding is set to 0 and stride is set to 1, the output size is 8x40x40, because                                                             (46−7)+1=40. Second Max-Pooling Layer        The second down-sampling layer uses max pooling with a 2x2 kernel and stride set to 2. This effectively drops the size     from 8x40x40 to 8x20x20. Third Convolutional Layer        The second convolutional layers expects 8 input channels and will convolve 16 filters each of size 8x5x5. Since     padding is set to 0 and stride is set to 1, the output size is 16x16x16, because                                                             (20−5)+1=16. Third Max-Pooling Layer        The second down-sampling layer uses max pooling with a 2x2 kernel and stride set to 2. This effectively drops the size     from 16x16x16 to 16x8x8.     First Fully-Connected Layer        The output from the final max pooling layer needs to be flattened so that we can connect it to a fully connected layer.     This is achieved using the torch.Tensor.view method. By specifying -1 the method will automatically infer the number of     rows required. This is done to handle the mini-batch size of data.    The fully-connected layer uses ReLU for activation and has 1024 nodes.     Second Fully-Connected Layer    The output from the first fully-connected layer is connected to another fully connected layer with 300 nodes, using     ReLU as an activation function. Output Layer        The last fully-connected layer uses softmax and is made up of ten nodes, one for each category in Fruit Dataset. So     total number of 15 nodes in the output layer.         ![Network Architecture](cnn_general.JPG)<jupyter_code>import torch.nn.functional as F
import torch.nn as nn

class Model(nn.Module):

    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=9, stride=1, padding=0)
        self.conv2 = nn.Conv2d(in_channels=6, out_channels=8, kernel_size=7, stride=1, padding=0)
        
        self.conv3 = nn.Conv2d(in_channels=8, out_channels=16, kernel_size=5, stride=1, padding=0)
        
        self.fc1 = nn.Linear(8*8*16, 300)
        self.fc2 = nn.Linear(300, Classes_num)

    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 = F.relu(self.conv3(x))
        x = F.max_pool2d(x, 2, 2)
        
        x = x.view(-1, 8*8*16)
        
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return F.log_softmax(x)
model = Model()
print(model)<jupyter_output>Model(
  (conv1): Conv2d(3, 6, kernel_size=(9, 9), stride=(1, 1))
  (conv2): Conv2d(6, 8, kernel_size=(7, 7), stride=(1, 1))
  (conv3): Conv2d(8, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=1024, out_features=300, bias=True)
  (fc2): Linear(in_features=300, out_features=15, bias=True)
)<jupyter_text>Define the loss function and the optimizer using the nn and optim package:<jupyter_code>import torch.optim as optim
# create a loss function
criterion = nn.CrossEntropyLoss()
# create a stochastic gradient descent optimizer
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)<jupyter_output><empty_output><jupyter_text>Model Training We are now ready to train the model. The core steps are Forward Propagation, Loss Computation, Backpropagation, and updating the parameters.<jupyter_code># run the main training loop
loss_array=[]
epochs=30
for epoch in range(1,epochs):
    
    for batch_idx, (data, target) in enumerate(train_loader):
        
        data, target = Variable(data), Variable(target)
        
        #In PyTorch, we need to set the gradients to zero before starting to do backpropragation because PyTorch
        optimizer.zero_grad()## accumulates the gradients on subsequent backward passes.
        
        ## 1. forward propagation
        model_out = model(data)
        
        ## 2. loss calculation
        loss = criterion(model_out, target)
        
        ## 3. backward propagation
        loss.backward()
        
        ## 4. weight optimization
        optimizer.step()
        
        loss_array.append(loss.item())
        
        if batch_idx % len(train_loader)-1 == 0:
            
            print('Epoch: ',epoch,'Loss: ', loss.item())
%matplotlib inline
plt.plot(loss_array)
plt.title("Training Loss")
plt.show()<jupyter_output><empty_output><jupyter_text>Model Testing Once the model is trained, Lets test it on test dataset.     1. Testing on some example<jupyter_code>## dataloader for test dataset 
dataiter = iter(test_loader)
data, labels = dataiter.next()
data, target = Variable(data), Variable(target)

output = model(data)
_, preds_tensor = torch.max(output, 1)
preds_tensor=preds_tensor.cpu()
preds = np.squeeze(preds_tensor.numpy())
print ("Actual:   ", np.array(labels[:10]))
print ("Predicted:", preds[:10])<jupyter_output>Actual:    [ 3 12  5  9 14 12 12  5  3 10]
Predicted: [ 3 12  5  9 14 12 12  5  3 10]<jupyter_text>2. Checking Accuracy of Model<jupyter_code># run a test loop
test_loss = 0
correct = 0
for data, target in test_loader:
    data, target = Variable(data), Variable(target)
    
    model_out = model(data)
    # sum up batch loss
    
    test_loss += criterion(model_out, target).item()
    pred = model_out.data.max(1)[1]  # get the index of the max log-probability
    correct += pred.eq(target.data).sum()

test_loss /= len(test_loader.dataset)

print('Average loss: ',test_loss)
print('Accuracy: ',np.array(100. * correct / len(test_sampler)),'%')
print ('Total Test Examples: ',len(test_sampler))
print ('Correct predicted Examples: ',int(correct))<jupyter_output>Average loss:  5.501896880061345e-06
Accuracy:  100 %
Total Test Examples:  1630
Correct predicted Examples:  1630
{'fraction_non_alphanumeric': 0.09246923337473185, 'fraction_numerical': 0.03691995032177938, 'mean_word_length': 3.514780835881753, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '577677', 'license': 'MIT', 'n_tokens_mistral': 2939, 'n_tokens_neox': 2655, 'n_words': 913, 'path': 'section7/Lecture49_CNN_Model.ipynb', 'repo_name': 'PacktPublishing/PyTorch-Bootcamp-for-Artificial-Neural-Networks-and-Deep-Learning-Applications', 'size': '8857'}