<jupyter_start><jupyter_text>Lab 01 : Point Cloud Classification - exerciseThe goal is to implement an architecture that classifies point clouds.<jupyter_code># For Google Colaboratory
import sys, os
if 'google.colab' in sys.modules:
    # mount google drive
    from google.colab import drive
    drive.mount('/content/gdrive')
    path_to_file = '/content/gdrive/My Drive/CS4243_codes/codes/labs_lecture13'
    print(path_to_file)
    # move to Google Drive directory
    os.chdir(path_to_file)
    !pwd
import torch
import torch.nn as nn
import torch.optim as optim
import utils
import time
#device= torch.device("cuda")
device= torch.device("cpu")
print(device)<jupyter_output><empty_output><jupyter_text>Generate the dataset<jupyter_code># Libraries
from torchvision.transforms import ToTensor
from PIL import Image
import matplotlib.pyplot as plt
import logging
logging.getLogger().setLevel(logging.CRITICAL) # remove warnings

# Import 5 object types
ob_size = 11
objects = torch.zeros(5,ob_size,ob_size)
nb_class_objects = 5
for k in range(nb_class_objects):
    objects[k,:,:] = 1-ToTensor()(Image.open('objects/obj'+str(k+1)+'.tif'))[0,:,:]
print(objects.size())
# Define the bounding boxes w.r.t. object type
def obj_legend(label):
    if label==0:
        color = 'r'; legend = 'Triangle'
    elif label==1:
        color = 'b'; legend = 'Cross'
    elif label==2:
        color = 'g'; legend = 'Star'
    elif label==3:
        color = 'y'; legend = 'Square'
    elif label==4:
        color = 'm'; legend = 'Ring'
    return color, legend

# Global constants
# im_size = image size  
# ob_size = object size
# batch_size = batch size
# nb_object_classes = number of object classes (we have 5 classes)
im_size = 28 
batch_size = 2
nb_object_classes = 5
nb_points = 35 # min=41 max=66

# Function that generate a batch of training data
def generate_batch_data(im_size, ob_size, batch_size, nb_points, nb_object_classes):
    batch_images = torch.zeros(batch_size,im_size,im_size)
    batch_points = torch.zeros(batch_size,nb_points,2)
    batch_labels = torch.zeros(batch_size)
    for b in range(batch_size):
        image = torch.zeros(im_size,im_size) 
        class_object = torch.LongTensor(1).random_(0,nb_object_classes)        
        offset = (ob_size-1)// 2 + 0
        coord_objects = torch.LongTensor(2).random_(offset,im_size-offset)
        # coord_objects[0] = x-coordinate,  coord_objects[1] = y-coordinate
        image[coord_objects[1]-offset:coord_objects[1]-offset+ob_size,coord_objects[0]-offset:coord_objects[0]-offset+ob_size] = objects[class_object,:,:]
        # find x,y s.t. image[y,x]=0.5
        obj_yx = torch.Tensor(plt.contour(image, [0.5]).collections[0].get_paths()[0].vertices); plt.clf() 
        obj_yx[:,[0,1]] = obj_yx[:,[1,0]]
        if class_object==4: # get the interior for the ring shape
            obj_yx_tmp = torch.Tensor(plt.contour(image, [0.5]).collections[0].get_paths()[1].vertices); plt.clf() 
            obj_yx_tmp[:,[0,1]] = obj_yx_tmp[:,[1,0]]
            obj_yx = torch.cat((obj_yx,obj_yx_tmp),dim=0)
        nb_yx_pts = obj_yx.size(0)
        if nb_yx_pts>=nb_points:
            idx_perm = torch.randperm(nb_yx_pts)[:nb_points]
            obj_yx = obj_yx[idx_perm,:]
        else: # in case of plt.contour does not extract enough data points
            obj_yx = obj_yx.repeat_interleave(nb_points//nb_yx_pts+1,dim=0)[:nb_points]
        batch_images[b,:,:] = image
        batch_points[b,:,:] = obj_yx
        batch_labels[b] = class_object
    return batch_images, batch_points, batch_labels

# Plot a mini-batch of images
batch_images, batch_points, batch_labels = generate_batch_data(im_size, ob_size, batch_size, nb_points, nb_object_classes)
print(batch_images.size())
print(batch_points.size())
print(batch_labels.size())
for b in range(batch_size):
    #plt.imshow(batch_images[b,:,:], cmap='gray')
    plt.imshow(torch.zeros(im_size,im_size), cmap='gray')
    color, legend = obj_legend(batch_labels[b])
    plt.scatter(batch_points[b,:,1],batch_points[b,:,0],marker='+',color=color,label=legend)
    plt.legend(loc='best')
    plt.colorbar()
    plt.title('Point Cloud')
    #plt.axis('off')
    plt.show() 

# Define the cloud network architecture
batch_size = 2 # for debug

class cloudNN(nn.Module):
    
    def __init__(self):
        super(cloudNN, self).__init__()
        hidden_dim = 250
        # first set layer
        # COMPLETE HERE
        
        # second set layer
        # COMPLETE HERE
        
        # classification layer
        # COMPLETE HERE
        
    def forward(self, x): 
        # first set layer
        # COMPLETE HERE
        
        # second set layer
        # COMPLETE HERE
        
        # classification layer
        # COMPLETE HERE
        
        return scores_cloud_class
    
# Instantiate the network
net = cloudNN()
net = net.to(device)
print(net)
utils.display_num_param(net) 

# Test the forward pass, backward pass and gradient update with a single batch
init_lr = 0.001
optimizer = torch.optim.Adam(net.parameters(), lr=init_lr)
batch_images, batch_points, batch_labels = generate_batch_data(im_size, ob_size, batch_size, nb_points, nb_object_classes)
optimizer.zero_grad()
scores_cloud_class = net(batch_points) # [batch_size, nb_object_classes] = [2, 5]
batch_labels = batch_labels.long() # [batch_size] = [2]
# loss
loss = nn.CrossEntropyLoss()(scores_cloud_class, batch_labels)
loss.backward()
optimizer.step()

# Training loop
net = cloudNN()
net = net.to(device)
utils.display_num_param(net) 

# Optimizer
init_lr = 0.001
optimizer = torch.optim.Adam(net.parameters(), lr=init_lr)

# Number of mini-batches per epoch
nb_batch = 10
batch_size = 10

start=time.time()
for epoch in range(10):

    running_loss = 0.0
    num_batches = 0
    
    for _ in range(nb_batch):
        
        # FORWARD AND BACKWARD PASS
        batch_images, batch_points, batch_labels = generate_batch_data(im_size, ob_size, batch_size, nb_points, nb_object_classes)
        optimizer.zero_grad()
        scores_cloud_class = net(batch_points) # [batch_size, nb_object_classes] = [2, 5]
        batch_labels = batch_labels.long() # [batch_size] = [2]
        # loss
        loss = nn.CrossEntropyLoss()(scores_cloud_class, batch_labels)
        loss.backward()
        optimizer.step()

        # COMPUTE STATS
        running_loss += loss.detach().item()
        num_batches += 1        
    
    # AVERAGE STATS THEN DISPLAY
    total_loss = running_loss/num_batches
    elapsed = (time.time()-start)/60
    print('epoch=',epoch, '\t time=', elapsed,'min', '\t lr=', init_lr  ,'\t loss=', total_loss )
    
# Test time

# select a batch of 2 images
batch_size = 5

# generate the batch of 2 images
batch_images, batch_points, batch_labels = generate_batch_data(im_size, ob_size, batch_size, nb_points, nb_object_classes)
        
# forward pass
scores_cloud_class = net(batch_points) # [batch_size, nb_object_classes]

# class prediction
pred_cloud_class = torch.argmax(scores_cloud_class, dim=1) # [batch_size] 

# Plot the ground truth solution and the predicted solution
for b in range(batch_size):

    #plt.imshow(batch_images[b,:,:], cmap='gray')
    plt.imshow(torch.zeros(im_size,im_size), cmap='gray')
    color, legend = obj_legend(batch_labels[b])
    plt.scatter(batch_points[b,:,1],batch_points[b,:,0],marker='+',color=color,label=legend)
    plt.legend(loc='best')
    plt.colorbar()
    plt.title('Ground Truth')
    plt.show() 
    
    #plt.imshow(batch_images[b,:,:], cmap='gray')
    plt.imshow(torch.zeros(im_size,im_size), cmap='gray')
    color, legend = obj_legend(pred_cloud_class[b])
    plt.scatter(batch_points[b,:,1],batch_points[b,:,0],marker='+',color=color,label=legend)
    plt.legend(loc='best')
    plt.colorbar()
    plt.title('Prediction')
    plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12469749076550758, 'fraction_numerical': 0.013756209400076424, 'mean_word_length': 3.6961722488038276, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '327609', 'license': 'MIT', 'n_tokens_mistral': 2827, 'n_tokens_neox': 2711, 'n_words': 568, 'path': 'codes/labs_lecture13/lecture13_point_cloud_classification_exercise.ipynb', 'repo_name': 'johanesrafael/CS4243_2022', 'size': '7851'}