#!/usr/bin/env python
# coding: utf-8
# # Q1.a. (10 points) create an network to approximate sin(x)
#
# In this problem, you will try to build a three-layer fully connected network to approximate the sin function using PyTorch. There are 100 hidden units in each layer and please use ReLU activation after the first two layers and no activation after the last layer. You should implement your network model as a subclass of [torch.nn.Module](https://pytorch.org/docs/stable/generated/torch.nn.Module.html)
# ### Define your network here
# In[1]:
import torch
from torch import nn
import numpy as np
import random
class Mynetwork(torch.nn.Module):
def __init__(self):
#-- complete the code here
#-- end complete the code here
def forward(self,x):
#-- complete the code here
#-- end complete the code here
# ### Training
# In[2]:
model = Mynetwork()
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters())
for epoch in range(10000):
x=10. * torch.rand((200,1)).type(torch.FloatTensor)
y=torch.sin(x).view(-1)
optimizer.zero_grad()
yh = model(x).view(-1)
loss = loss_fn(yh,y)
loss.backward()
optimizer.step()
if epoch % 1000 == 999:
print(loss.item())
# ### Visualization
# In[3]:
from matplotlib import pyplot as plt
xv=np.array(range(100))/50. *np.pi
yv=model(torch.from_numpy(xv).type(torch.FloatTensor).view((100,-1))).view(-1).detach().numpy()
plt.plot(xv,yv,label='network')
plt.plot(xv,np.sin(xv),label='sin(x)')
plt.legend()
# # Q1.b. (Extra credit: 5 points) Repeat 1.a. using [torch.nn.Sequential](https://pytorch.org/docs/stable/generated/torch.nn.Sequential.html)
#
# ### Redefine your model below
# In[4]:
# Hint: model = torch.nn.Sequential(...)
#-- complete the code here
#-- end complete the code here
# ### Training
# In[5]:
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters())
for epoch in range(10000):
x=10. * torch.rand((200,1)).type(torch.FloatTensor)
y=torch.sin(x).view(-1)
optimizer.zero_grad()
yh = model(x).view(-1)
loss = loss_fn(yh,y)
loss.backward()
optimizer.step()
if epoch % 1000 == 999:
print(loss.item())
# ### Visualization
# In[6]:
from matplotlib import pyplot as plt
xv=np.array(range(100))/50. *np.pi
yv=model(torch.from_numpy(xv).type(torch.FloatTensor).view((100,-1))).view(-1).detach().numpy()
plt.plot(xv,yv,label='network')
plt.plot(xv,np.sin(xv),label='sin(x)')
plt.legend()
# # Q2. Classify clothing
#
# In this problem, you will implement a network to classify different types of clothing. We will play with the [FachionMNIST](https://github.com/zalandoresearch/fashion-mnist) dataset, which contains ten different classes.
#
# Your network should contain three conv layers with 6, 16, and 32 filters (all 3x3 and no padding), respectively. You should use ReLU activation after each conv layer followed by 2x2 max pooling. There will be two fully connected layers after the last pooling layer. The first fully connected layer has 64 neurons.
# # Q2.a. (2 points) How many outputs for the last fully connected layer (Hint: there are 10 classes)
# Answer:
# # Q2.b (6 points) How many parameters in the entire network?
# Answer:
#
# conv 1:
#
# pooling 1:
#
# conv2:
#
# pooling 2:
#
# conv3:
#
# pooling 3:
#
# fully-connected 1:
#
# fully-connected 2:
#
#
# # Q2.c (12 points) Complete the code below by defining the network
# ### Download and load the dataset
# In[7]:
import torch
import torchvision
import torchvision.transforms as transforms
use_cuda = False # set it to True if you have GPU and want to use it
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))])
# Create datasets for training & validation, download if necessary
training_set = torchvision.datasets.FashionMNIST('./data', train=True, transform=transform, download=True)
validation_set = torchvision.datasets.FashionMNIST('./data', train=False, transform=transform, download=True)
# Create data loaders for our datasets; shuffle for training, not for validation
training_loader = torch.utils.data.DataLoader(training_set, batch_size=4, shuffle=True, num_workers=2)
validation_loader = torch.utils.data.DataLoader(validation_set, batch_size=4, shuffle=False, num_workers=2)
# Class labels
classes = ('T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle Boot')
# Report split sizes
print('Training set has {} instances'.format(len(training_set)))
print('Validation set has {} instances'.format(len(validation_set)))
# ### Visualize the dataset
# In[8]:
import matplotlib.pyplot as plt
import numpy as np
# Helper function for inline image display
def matplotlib_imshow(img, one_channel=False):
if one_channel:
img = img.mean(dim=0)
img = img / 2 + 0.5 # unnormalize
npimg = img.numpy()
if one_channel:
plt.imshow(npimg, cmap="Greys")
else:
plt.imshow(np.transpose(npimg, (1, 2, 0)))
dataiter = iter(training_loader)
images, labels = dataiter.next()
# Create a grid from the images and show them
img_grid = torchvision.utils.make_grid(images)
matplotlib_imshow(img_grid, one_channel=True)
print(' '.join(classes[labels[j]] for j in range(4)))
# ### Define your network here
# In[9]:
import torch.nn as nn
import torch
import torch.nn.functional as F
class GarmentClassifier(nn.Module):
def __init__(self):
#-- complete the code here
#-- end complete the code here
def forward(self, x):
#-- complete the code here
#-- end complete the code here
if torch.cuda.is_available() and use_cuda:
model = GarmentClassifier().cuda()
else:
model = GarmentClassifier()
# ### Prepare "trainer"
# In[13]:
loss_fn = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
def train_one_epoch(epoch_index):
running_loss = 0.
last_loss = 0.
# Here, we use enumerate(training_loader) instead of
# iter(training_loader) so that we can track the batch
# index and do some intra-epoch reporting
for i, data in enumerate(training_loader):
# Every data instance is an input + label pair
inputs, labels = data
if torch.cuda.is_available() and use_cuda:
inputs=inputs.cuda()
labels=labels.cuda()
# Zero your gradients for every batch!
optimizer.zero_grad()
# Make predictions for this batch
outputs = model(inputs)
# Compute the loss and its gradients
loss = loss_fn(outputs, labels)
loss.backward()
# Adjust learning weights
optimizer.step()
# Gather data and report
running_loss += loss.item()
if i % 1000 == 999:
last_loss = running_loss / 1000 # loss per batch
print(' batch {} loss: {}'.format(i + 1, last_loss))
running_loss = 0.
return last_loss
# ### Start training
# In[15]:
# Initializing in a separate cell so we can easily add more epochs to the same run
torch.multiprocessing.set_sharing_strategy('file_system')
# timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
# writer = SummaryWriter('runs/fashion_trainer_{}'.format(timestamp))
epoch_number = 0
EPOCHS = 3
best_vloss = 1_000_000.
for epoch in range(EPOCHS):
print('EPOCH {}:'.format(epoch_number + 1))
# Make sure gradient tracking is on, and do a pass over the data
model.train(True)
avg_loss = train_one_epoch(epoch_number)
# We don't need gradients on to do reporting
model.train(False)
running_vloss = 0.0
for i, vdata in enumerate(validation_loader):
vinputs, vlabels = vdata
if torch.cuda.is_available() and use_cuda:
vinputs=vinputs.cuda()
vlabels=vlabels.cuda()
voutputs = model(vinputs)
vloss = loss_fn(voutputs, vlabels)
running_vloss += vloss
avg_vloss = running_vloss / (i + 1)
print('LOSS train {} valid {}'.format(avg_loss, avg_vloss))
# Track best performance, and save the model's state
if avg_vloss < best_vloss:
best_vloss = avg_vloss
epoch_number += 1
# ### Verify results
# In[16]:
dataiter = iter(validation_loader)
images, labels = dataiter.next()
# Create a grid from the images and show them
img_grid = torchvision.utils.make_grid(images)
matplotlib_imshow(img_grid, one_channel=True)
print('Groundtruth: '+' '.join(classes[labels[j]] for j in range(4)))
if torch.cuda.is_available() and use_cuda:
images=images.cuda()
print('Result: '+' '.join([classes[i] for i in torch.argmax(model(images).cpu(),1)]))
# # Q2.d (Extra credit: 10 points) Try to see if you can modify the network so that the validation loss is less than 0.3 and the number of parameters are no more than 5% more than the original one
#
# # Q3. Object detection with YOLOv5
#
# Please follow the instructions [here](https://pytorch.org/hub/ultralytics_yolov5/) to install YOLOv5 on PyTorch.
#
#
# # Q3.a (10 points) Test YOLOv5s on one of your own photos. Show your code and results.
# # Q3.b (Extra credit: 5 points) Combine YOLO and OpenCV to detect object from webcam stream by completing the code below (Hint: dir(model(frame)))
# ### Complete the code below
# In[17]:
import cv2
import platform
cap=cv2.VideoCapture(0)
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
while (True):
ret,frame=cap.read()
results = model(frame)
#-- complete the code here
#-- end complete the code here
if cv2.waitKey(1) &0xFF == ord('q'): # press q or ESC to quit. You probably need to hit the screen first
break
cap.release()
cv2.destroyAllWindows()
# In[ ]: