SKELY Baseline

Contribute Download Execute In Colab

Baseline for SKELY Challenge on AIcrowd

Author : Sharada Mohanty

Download Necessary Packages

In [1]:
import sys
!pip install numpy
!pip install pandas
!pip install scikit-learn 
!pip install matplotlib tqdm
Requirement already satisfied: numpy in /usr/local/lib/python3.6/dist-packages (1.18.5)
Requirement already satisfied: pandas in /usr/local/lib/python3.6/dist-packages (1.0.5)
Requirement already satisfied: numpy>=1.13.3 in /usr/local/lib/python3.6/dist-packages (from pandas) (1.18.5)
Requirement already satisfied: python-dateutil>=2.6.1 in /usr/local/lib/python3.6/dist-packages (from pandas) (2.8.1)
Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.6/dist-packages (from pandas) (2018.9)
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.6/dist-packages (from python-dateutil>=2.6.1->pandas) (1.12.0)
Requirement already satisfied: scikit-learn in /usr/local/lib/python3.6/dist-packages (0.22.2.post1)
Requirement already satisfied: joblib>=0.11 in /usr/local/lib/python3.6/dist-packages (from scikit-learn) (0.15.1)
Requirement already satisfied: scipy>=0.17.0 in /usr/local/lib/python3.6/dist-packages (from scikit-learn) (1.4.1)
Requirement already satisfied: numpy>=1.11.0 in /usr/local/lib/python3.6/dist-packages (from scikit-learn) (1.18.5)
Requirement already satisfied: matplotlib in /usr/local/lib/python3.6/dist-packages (3.2.2)
Requirement already satisfied: tqdm in /usr/local/lib/python3.6/dist-packages (4.41.1)
Requirement already satisfied: numpy>=1.11 in /usr/local/lib/python3.6/dist-packages (from matplotlib) (1.18.5)
Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib) (2.4.7)
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib) (0.10.0)
Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib) (1.2.0)
Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib) (2.8.1)
Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from cycler>=0.10->matplotlib) (1.12.0)

Download data

The first step is to download the training data and the test data

In [ ]:
# #Donwload the datasets
!rm -rf data/
!mkdir data/

!curl https://s3.eu-central-1.wasabisys.com/aicrowd-practice-challenges/public/skely/v0.1/train.tar.gz -o data/train.tar.gz
!curl https://s3.eu-central-1.wasabisys.com/aicrowd-practice-challenges/public/skely/v0.1/test.tar.gz -o data/test.tar.gz
!curl https://s3.eu-central-1.wasabisys.com/aicrowd-practice-challenges/public/skely/v0.1/sample_submission.csv -o data/sample_submission.csv
!tar xvzf data/train.tar.gz -C data/
!tar xvzf data/test.tar.gz -C data/
In [5]:
## Now the data is available at the following locations:

TRAINING_IMAGES_FOLDER = "data/training/images/"
TRAINING_LABELS_PATH = "data/training/labels.csv"
TEST_IMAGES_FOLDER = "data/images"
SAMPLE_SUBMISSION_FILE_PATH = "data/sample_submission.csv"

Import packages

In [6]:
import os
import tqdm

import pandas as pd
import numpy as np

from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPRegressor
from sklearn.metrics import mean_squared_error,mean_absolute_error
import matplotlib.pyplot as plt
%matplotlib inline

from PIL import Image

Load Data

We use PIL library to load our images. Here we are creating our array where our input features are the mean colours and output features are the rotations along the x axis.

In [7]:
training_labels_df = pd.read_csv(TRAINING_LABELS_PATH)

def pre_process_data_X(image):
    """
    This file takes a loaded image and returns a particular 
    representation of the data point
    
    
    NOTE: This current baseline implements a **very** silly approach
    of representing every image by the mean RGB values for every image.
    
    You are encourage to try to alternate representations of the data,
    or figure out how to learn the best representation from the data ;)
    """
    im_array = np.array(im)
    mean_rgb = im_array.mean(axis=(0, 1))
    return mean_rgb


ALL_DATA = []

for _idx, row in tqdm.tqdm(training_labels_df.iterrows(), total=training_labels_df.shape[0]):
    filepath = os.path.join(
        TRAINING_IMAGES_FOLDER,
        row.filename
    )
    im = Image.open(filepath)
    
    data_X = pre_process_data_X(im)
    data_Y = [row.xRot]
    
    ALL_DATA.append((data_X, data_Y))
100%|██████████| 9999/9999 [24:37<00:00,  6.77it/s]

Exploratory Data Analysis

We now see the kind of images the dataset contains to get a better idea. The title signifies clockwise rotation of the cube along the x axis

In [8]:
plt.figure(figsize=(20,20))
for i in range(16):
  filename,xRot = training_labels_df.iloc[i]
  filepath = os.path.join(
        TRAINING_IMAGES_FOLDER,
        filename
    )
  im = Image.open(filepath)
  plt.subplot(4,4,i+1)
  plt.axis('off')
  plt.title("xRot: %.3f"%(xRot))
  plt.imshow(im)

Split Data into Train and Validation

We split the dataset into Training data and Validation datasets to help us test the generalizability of our models, and to ensure that we are not overfitting on the training set.

In [9]:
training_set, validation_set= train_test_split(ALL_DATA, test_size=0.2, random_state=42)

Here we have selected the size of the testing data to be 20% of the total data. You can change it and see what effect it has on the accuracies. To learn more about the train_test_split function click here.

Now, since we have our data splitted into train and validation sets, we need to get the label separated from the data.

In [10]:
X_train, y_train = zip(*training_set)
X_val, y_val = zip(*validation_set)


X_train = np.array(X_train)
y_train = np.array(y_train)
X_val = np.array(X_val)
y_val = np.array(y_val)

Define the Classifier

Now we finally come to the juicy part. Now that all the data is all loaded and available nice, we can finally get to training the classifier. Here we use sklearn MLPRegressor to train our network. We can tune the hyper parameters based on cross validation scores

In [11]:
model = MLPRegressor(hidden_layer_sizes=[10, 10], verbose=True)
# NOTE : This is again silly hyper parameter instantiation of this problem,
# and we encourage you to explore what works the best for you.

Train the classifier

In [12]:
model.fit(X_train, y_train)
/usr/local/lib/python3.6/dist-packages/sklearn/neural_network/_multilayer_perceptron.py:1342: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
  y = column_or_1d(y, warn=True)
Iteration 1, loss = 41129.48898644
Iteration 2, loss = 22749.22529257
Iteration 3, loss = 10433.89035716
Iteration 4, loss = 4334.56568262
Iteration 5, loss = 3627.21814731
Iteration 6, loss = 3497.38697087
Iteration 7, loss = 3410.92176757
Iteration 8, loss = 3350.87261289
Iteration 9, loss = 3307.94813312
Iteration 10, loss = 3277.05173166
Iteration 11, loss = 3255.41088791
Iteration 12, loss = 3238.21565847
Iteration 13, loss = 3226.10013849
Iteration 14, loss = 3215.62099961
Iteration 15, loss = 3209.04319212
Iteration 16, loss = 3204.08637621
Iteration 17, loss = 3199.64622032
Iteration 18, loss = 3194.87411342
Iteration 19, loss = 3192.88077696
Iteration 20, loss = 3188.89238840
Iteration 21, loss = 3185.88886666
Iteration 22, loss = 3182.90967462
Iteration 23, loss = 3180.37219268
Iteration 24, loss = 3177.31085348
Iteration 25, loss = 3175.35553604
Iteration 26, loss = 3174.59038159
Iteration 27, loss = 3171.18820111
Iteration 28, loss = 3171.80883233
Iteration 29, loss = 3168.11986281
Iteration 30, loss = 3167.12714901
Iteration 31, loss = 3165.90271500
Iteration 32, loss = 3163.72896420
Iteration 33, loss = 3162.99566519
Iteration 34, loss = 3159.70243238
Iteration 35, loss = 3160.54293164
Iteration 36, loss = 3158.64894875
Iteration 37, loss = 3158.92149692
Iteration 38, loss = 3157.13702564
Iteration 39, loss = 3155.79039544
Iteration 40, loss = 3156.77559858
Iteration 41, loss = 3156.02577152
Iteration 42, loss = 3155.38361150
Iteration 43, loss = 3154.76344489
Iteration 44, loss = 3154.19670827
Iteration 45, loss = 3155.20920000
Iteration 46, loss = 3154.79027312
Iteration 47, loss = 3155.05223932
Iteration 48, loss = 3153.03177163
Iteration 49, loss = 3155.79044980
Iteration 50, loss = 3151.18994305
Iteration 51, loss = 3153.83254398
Iteration 52, loss = 3151.14588128
Iteration 53, loss = 3152.52969406
Iteration 54, loss = 3152.79788152
Iteration 55, loss = 3150.29169017
Iteration 56, loss = 3155.19621927
Iteration 57, loss = 3151.88615217
Iteration 58, loss = 3154.44428093
Iteration 59, loss = 3151.58263447
Iteration 60, loss = 3150.94342039
Iteration 61, loss = 3152.11028503
Iteration 62, loss = 3155.70202936
Iteration 63, loss = 3150.05913491
Iteration 64, loss = 3149.86324136
Iteration 65, loss = 3149.94083347
Iteration 66, loss = 3148.44259750
Iteration 67, loss = 3151.33379733
Iteration 68, loss = 3147.79127864
Iteration 69, loss = 3149.96788541
Iteration 70, loss = 3149.86026312
Iteration 71, loss = 3149.99296721
Iteration 72, loss = 3149.98226714
Iteration 73, loss = 3148.44037419
Iteration 74, loss = 3147.58219246
Iteration 75, loss = 3152.74194843
Iteration 76, loss = 3152.11606232
Iteration 77, loss = 3149.90136048
Iteration 78, loss = 3147.88396723
Iteration 79, loss = 3148.91335382
Iteration 80, loss = 3151.32899668
Iteration 81, loss = 3149.12262726
Iteration 82, loss = 3148.30160185
Iteration 83, loss = 3149.71028097
Iteration 84, loss = 3153.66219401
Iteration 85, loss = 3150.77542646
Training loss did not improve more than tol=0.000100 for 10 consecutive epochs. Stopping.
Out[12]:
MLPRegressor(activation='relu', alpha=0.0001, batch_size='auto', beta_1=0.9,
             beta_2=0.999, early_stopping=False, epsilon=1e-08,
             hidden_layer_sizes=[10, 10], learning_rate='constant',
             learning_rate_init=0.001, max_fun=15000, max_iter=200,
             momentum=0.9, n_iter_no_change=10, nesterovs_momentum=True,
             power_t=0.5, random_state=None, shuffle=True, solver='adam',
             tol=0.0001, validation_fraction=0.1, verbose=True,
             warm_start=False)

Predict on Validation

Now we predict our trained classifier on the validation set and evaluate our model

In [13]:
y_pred = model.predict(X_val)

Evaluate the Performance

We use the same metrics as that will be used for the test set.
MAE and RMSE are the metrics for this challenge

In [14]:
print('Mean Absolute Error:', mean_absolute_error(y_val, y_pred))  
print('Mean Squared Error:', mean_squared_error(y_val, y_pred))  
print('Root Mean Squared Error:', np.sqrt(mean_squared_error(y_val, y_pred)))
Mean Absolute Error: 61.98061951516751
Mean Squared Error: 5883.760753664069
Root Mean Squared Error: 76.70567615023069

Load Test Set

Load the test data now

In [19]:
import glob

TEST_DATA = []
TEST_FILENAMES = []

for _test_image_path in tqdm.tqdm(glob.glob(os.path.join(TEST_IMAGES_FOLDER, "*.png"))):
    filename = os.path.basename(_test_image_path)
    im = Image.open(_test_image_path)
    
    data_X = pre_process_data_X(im)
    TEST_DATA.append(data_X)
    TEST_FILENAMES.append(filename)
100%|██████████| 10001/10001 [24:50<00:00,  6.71it/s]
In [20]:
TEST_DATA = np.array(TEST_DATA)
# model = classifier

Make predictions on the test set

In [21]:
test_predictions = model.predict(TEST_DATA)
In [22]:
test_df = pd.DataFrame(test_predictions, columns=['xRot'])
test_df["filename"] = TEST_FILENAMES

Save the prediction to csv

In [23]:
test_df.to_csv('submission.csv', index=False)

Note: Do take a look at the submission format.The submission file should contain the following header : filename,xRot.

To download the generated csv in Google Colab run the below command

In [24]:
from google.colab import files
files.download('submission.csv')

Well Done! 👍 We are all set to make a submission and see your name on leaderborad. Lets navigate to challenge page and make one.

In [ ]: