Learn data science and machine learning by building real-world projects on Jovian

Relative Humidity prediction using linear regression (minimal)

Using the boston housing dataset: https://archive.ics.uci.edu/ml/datasets/Air+Quality

In [1]:
# Uncomment and run the commands below if imports fail
!conda install numpy pytorch torchvision cpuonly -c pytorch -y
!pip install matplotlib --upgrade --quiet
!pip install jovian --upgrade --quiet
Collecting package metadata (current_repodata.json): done Solving environment: done ## Package Plan ## environment location: /opt/conda added / updated specs: - cpuonly - numpy - pytorch - torchvision The following packages will be downloaded: package | build ---------------------------|----------------- ca-certificates-2020.4.5.2 | hecda079_0 147 KB conda-forge certifi-2020.4.5.2 | py37hc8dfbb8_0 152 KB conda-forge numpy-1.18.5 | py37h8960a57_0 5.1 MB conda-forge ------------------------------------------------------------ Total: 5.4 MB The following packages will be UPDATED: ca-certificates 2020.4.5.1-hecc5488_0 --> 2020.4.5.2-hecda079_0 certifi 2020.4.5.1-py37hc8dfbb8_0 --> 2020.4.5.2-py37hc8dfbb8_0 numpy 1.18.1-py37h8960a57_1 --> 1.18.5-py37h8960a57_0 Downloading and Extracting Packages certifi-2020.4.5.2 | 152 KB | ##################################### | 100% numpy-1.18.5 | 5.1 MB | ##################################### | 100% ca-certificates-2020 | 147 KB | ##################################### | 100% Preparing transaction: done Verifying transaction: done Executing transaction: done
In [2]:
# Imports
import torch
import jovian
import torchvision
import torch.nn as nn
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import torch.nn.functional as F
from datetime import *
from torchvision.datasets.utils import download_url
from torch.utils.data import DataLoader, TensorDataset, random_split

Read file

In [3]:
dataframe = pd.read_csv('../input/airquality-uci/AirQualityUCI.csv', delimiter =';', decimal= ',')
# here you have to use delimiter ';' which will make your raw data into tabular form with colums and rows
# decimal = ',' makes your column values seperated with dot rather than comma
dataframe.head()
# , parse_dates = [['Date', 'Time']]
Out[3]:

Check Rows and Columns

In [4]:
dataframe.shape
Out[4]:
(9471, 17)

Remove Columns with missing values

To drop rows or cos in csv, we use dropna() axis = 1 means columns how = 'all' means if all column values are null, we will drop inplace = 'True' means that this drop() will affect the origianl dataframe.

In [5]:
drop_dataframe = dataframe.dropna(axis = 1, how = 'all', inplace = True)

axis = 0 means index

In [6]:
drop_dataframe = dataframe.dropna(axis = 0, how = 'all')
In [7]:
drop_dataframe.tail()
Out[7]:
In [8]:
drop_dataframe.isna() # check if there's null 
# return False if no null
Out[8]:

Rename columns

In [9]:
drop_dataframe = drop_dataframe.rename(columns={'T': 'Temperature(\u2103)',
                                                'RH': 'Relative Humidity(%)',
                                                'AH': 'Absolute Humidity'})
drop_dataframe.head()
# For degree Celsius symbol, you can use the followings. Both work. 
# 'Temperature \N{DEGREE SIGN}C'
# 'Temperature(\u2103)'
Out[9]:

Extract Date and Time

In [10]:
# however our date is in string format 
# extract date, month and year from date 
drop_dataframe['Day'] = pd.DatetimeIndex(drop_dataframe['Date']).day
drop_dataframe['month'] = pd.DatetimeIndex(drop_dataframe['Date']).month
drop_dataframe['year'] = pd.DatetimeIndex(drop_dataframe['Date']).year
drop_dataframe.head()
Out[10]:
In [11]:
# Time is in string format in the given data.
# So we cannot usse datetime.hour to select it. 
# We will extract hour by the followings. 
drop_dataframe['Hour']=drop_dataframe['Time'].apply(lambda x: str(x)[0:2])
# what we want is float type and so convert string to float or int
drop_dataframe['Hour']= drop_dataframe['Hour'].apply(lambda x: float(x))
drop_dataframe.dtypes
Out[11]:
Date                     object
Time                     object
CO(GT)                  float64
PT08.S1(CO)             float64
NMHC(GT)                float64
C6H6(GT)                float64
PT08.S2(NMHC)           float64
NOx(GT)                 float64
PT08.S3(NOx)            float64
NO2(GT)                 float64
PT08.S4(NO2)            float64
PT08.S5(O3)             float64
Temperature(℃)          float64
Relative Humidity(%)    float64
Absolute Humidity       float64
Day                       int64
month                     int64
year                      int64
Hour                    float64
dtype: object
In [12]:
# remove date and time columns
df = drop_dataframe.drop(['Date', 'Time'], axis = 1)
df.head()
Out[12]:
In [13]:
df.shape
Out[13]:
(9357, 17)
In [14]:
import os 
os.chdir(r'/kaggle/working')
df.to_csv(r'df.csv')

Select inputs and target

In [96]:
# To convert into Tensor, select columns in list form. If it is not numpy, you will see an error. 
input_cols = list(df.drop(['Relative Humidity(%)'], axis = 1)) 
#target_cols = list(df.columns)[11]
target_cols = list(df.drop(input_cols, axis = 1))
print('input_cols:', input_cols, '\n')
print('target_cols: ', target_cols)
input_cols: ['CO(GT)', 'PT08.S1(CO)', 'NMHC(GT)', 'C6H6(GT)', 'PT08.S2(NMHC)', 'NOx(GT)', 'PT08.S3(NOx)', 'NO2(GT)', 'PT08.S4(NO2)', 'PT08.S5(O3)', 'Temperature(℃)', 'Absolute Humidity', 'Day', 'month', 'year', 'Hour'] target_cols: ['Relative Humidity(%)']
In [97]:
# convert to numpy
input_arrays = drop_dataframe[input_cols].to_numpy()
target_arrays = drop_dataframe[target_cols].to_numpy()
input_arrays.shape, target_arrays.shape
#target_arrays
Out[97]:
((9357, 16), (9357, 1))
In [40]:
# convert input and targets into Pytorch Tensor, make sure data type is torch.float32
inputs = torch.from_numpy(np.array(input_arrays, dtype = 'float32'))
targets = torch.from_numpy(np.array(target_arrays, dtype = 'float32'))

Next, we need to create PyTorch datasets & data loaders for training & validation. We'll start by creating a TensorDataset.

Prepare DataSet

In [41]:
dataset = TensorDataset(inputs, targets)

To determine the fraction of data that will be used for creating the validation set, we will use 0.2. It means that you use 80% for training, 20 % for validation from the given data. Then use random_split to create training & validation datasets.

In [42]:
val_percent = 0.2 
num_rows = df.shape[0]
num_cols = df.shape[1]
val_size = int(num_rows * val_percent)
train_size = num_rows - val_size


train_ds, val_ds = random_split(dataset, [val_size, train_size])

We will define batch size which is good for memory. If you train all data at the same time, your training will take a huge time.

In [43]:
batch_size = 64
In [44]:
train_loader = DataLoader(train_ds, batch_size, shuffle=True)
# need to shuffle the train_ds for better result
val_loader = DataLoader(val_ds, batch_size)
# validation dataset does not to be shuffled because it is just for fit and evaluation

Check if it's working fine.

In [45]:
df.head()
Out[45]:
In [46]:
for xb, yb in train_loader:
    print("inputs:", xb)
    print("targets:", yb)
    break

# you won't see the same number in the same place as shown in above table because you shuffled the data 
inputs: tensor([[ 1.1000e+00, 9.1900e+02, -2.0000e+02, ..., 1.1000e+01, 2.0040e+03, 1.0000e+00], [ 9.0000e-01, 9.2000e+02, -2.0000e+02, ..., 1.0000e+01, 2.0040e+03, 8.0000e+00], [ 1.5000e+00, 1.0190e+03, -2.0000e+02, ..., 7.0000e+00, 2.0040e+03, 1.2000e+01], ..., [ 1.4000e+00, 1.0700e+03, -2.0000e+02, ..., 8.0000e+00, 2.0040e+03, 1.2000e+01], [ 2.6000e+00, -2.0000e+02, 2.6200e+02, ..., 9.0000e+00, 2.0040e+03, 1.1000e+01], [-2.0000e+02, 9.4100e+02, -2.0000e+02, ..., 1.0000e+01, 2.0040e+03, 4.0000e+00]]) targets: tensor([[ 39.5000], [ 66.7000], [ 17.2000], [ 41.0000], [ 41.4000], [-200.0000], [-200.0000], [ 68.3000], [ 50.4000], [ 47.3000], [ 46.8000], [ 50.1000], [ 37.6000], [ 18.3000], [ 27.0000], [ 40.1000], [ 63.3000], [ 66.8000], [ 17.8000], [ 43.0000], [ 64.1000], [ 62.1000], [ 49.8000], [ 26.5000], [ 45.9000], [ 20.5000], [ 82.1000], [ 57.9000], [ 48.7000], [ 15.0000], [ 78.3000], [ 39.2000], [ 18.0000], [ 17.9000], [ 22.9000], [ 50.9000], [ 35.3000], [ 35.6000], [ 38.5000], [ 49.4000], [ 66.0000], [ 57.8000], [ 44.8000], [ 47.0000], [ 56.9000], [ 61.4000], [ 74.3000], [ 34.2000], [ 46.8000], [ 72.8000], [ 38.8000], [ 9.9000], [ 57.8000], [ 41.5000], [ 76.0000], [ 26.2000], [ 32.3000], [ 40.7000], [ 52.3000], [ 81.6000], [ 48.8000], [ 15.8000], [-200.0000], [ 64.0000]])
In [47]:
target_arrays
Out[47]:
array([[48.9],
       [47.7],
       [54. ],
       ...,
       [18.3],
       [13.5],
       [13.1]])

Create a linear Regression Model

In [48]:
input_size = len(input_cols)
output_size = len(target_cols)
In [59]:
class AQModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(input_size, output_size) # fill this (hint: use input_size & output_size defined above)
        
    def forward(self, xb):
        out = self.linear(xb)                          # fill this
        return out
    
    def training_step(self, batch):
        inputs, targets = batch 
        # Generate predictions
        out = self(inputs)          
        # Calcuate loss
        loss = F.l1_loss(out,targets)                      # fill this
        return loss
    
    def validation_step(self, batch):
        inputs, targets = batch
        # Generate predictions
        out = self(inputs)
        # Calculate loss
        loss = F.l1_loss(out,targets)                          # fill this    
        return {'val_loss': loss.detach()}
        
    def validation_epoch_end(self, outputs):
        batch_losses = [x['val_loss'] for x in outputs]
        epoch_loss = torch.stack(batch_losses).mean()   # Combine losses
        return {'val_loss': epoch_loss.item()}
    
    def epoch_end(self, epoch, result, num_epochs):
        # Print result every 20th epoch
        if (epoch+1) % 20 == 0 or epoch == num_epochs-1:
            print("Epoch [{}], val_loss: {:.4f}".format(epoch+1, result['val_loss']))
            
model = AQModel()

Training

In [60]:
def evaluate(model, val_loader):
    outputs = [model.validation_step(batch) for batch in val_loader]
    return model.validation_epoch_end(outputs)

def fit(epochs, lr, model, train_loader, val_loader, opt_func=torch.optim.SGD):
    history = []
    optimizer = opt_func(model.parameters(), lr)
    for epoch in range(epochs):
        # Training Phase 
        for batch in train_loader:
            loss = model.training_step(batch)
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()
        # Validation phase
        result = evaluate(model, val_loader)
        model.epoch_end(epoch, result, epochs)
        history.append(result)
    return history
In [61]:
result = evaluate(model, val_loader) # Before using model
print(result)
{'val_loss': 452.1524353027344}
In [85]:
model = AQModel()
epochs = 10000
lr = 1e-8
history = fit(epochs, lr, model, train_loader, val_loader)
Epoch [20], val_loss: 151.7095 Epoch [40], val_loss: 136.5500 Epoch [60], val_loss: 127.4793 Epoch [80], val_loss: 122.1163 Epoch [100], val_loss: 118.8751 Epoch [120], val_loss: 116.7115 Epoch [140], val_loss: 115.2012 Epoch [160], val_loss: 113.9992 Epoch [180], val_loss: 112.9420 Epoch [200], val_loss: 111.9667 Epoch [220], val_loss: 111.0467 Epoch [240], val_loss: 110.1555 Epoch [260], val_loss: 109.2838 Epoch [280], val_loss: 108.4165 Epoch [300], val_loss: 107.5654 Epoch [320], val_loss: 106.7293 Epoch [340], val_loss: 105.9013 Epoch [360], val_loss: 105.0763 Epoch [380], val_loss: 104.2632 Epoch [400], val_loss: 103.4571 Epoch [420], val_loss: 102.6613 Epoch [440], val_loss: 101.8687 Epoch [460], val_loss: 101.0882 Epoch [480], val_loss: 100.3057 Epoch [500], val_loss: 99.5311 Epoch [520], val_loss: 98.7617 Epoch [540], val_loss: 97.9950 Epoch [560], val_loss: 97.2339 Epoch [580], val_loss: 96.4803 Epoch [600], val_loss: 95.7357 Epoch [620], val_loss: 94.9952 Epoch [640], val_loss: 94.2585 Epoch [660], val_loss: 93.5327 Epoch [680], val_loss: 92.8092 Epoch [700], val_loss: 92.0748 Epoch [720], val_loss: 91.3490 Epoch [740], val_loss: 90.6312 Epoch [760], val_loss: 89.9209 Epoch [780], val_loss: 89.2138 Epoch [800], val_loss: 88.5134 Epoch [820], val_loss: 87.8189 Epoch [840], val_loss: 87.1261 Epoch [860], val_loss: 86.4477 Epoch [880], val_loss: 85.7742 Epoch [900], val_loss: 85.0984 Epoch [920], val_loss: 84.4350 Epoch [940], val_loss: 83.7707 Epoch [960], val_loss: 83.1115 Epoch [980], val_loss: 82.4451 Epoch [1000], val_loss: 81.7928 Epoch [1020], val_loss: 81.1477 Epoch [1040], val_loss: 80.5023 Epoch [1060], val_loss: 79.8616 Epoch [1080], val_loss: 79.2294 Epoch [1100], val_loss: 78.6091 Epoch [1120], val_loss: 77.9935 Epoch [1140], val_loss: 77.3896 Epoch [1160], val_loss: 76.7904 Epoch [1180], val_loss: 76.1952 Epoch [1200], val_loss: 75.6118 Epoch [1220], val_loss: 75.0286 Epoch [1240], val_loss: 74.4474 Epoch [1260], val_loss: 73.8723 Epoch [1280], val_loss: 73.3025 Epoch [1300], val_loss: 72.7459 Epoch [1320], val_loss: 72.1920 Epoch [1340], val_loss: 71.6450 Epoch [1360], val_loss: 71.1007 Epoch [1380], val_loss: 70.5643 Epoch [1400], val_loss: 70.0298 Epoch [1420], val_loss: 69.5015 Epoch [1440], val_loss: 68.9775 Epoch [1460], val_loss: 68.4616 Epoch [1480], val_loss: 67.9535 Epoch [1500], val_loss: 67.4593 Epoch [1520], val_loss: 66.9775 Epoch [1540], val_loss: 66.5152 Epoch [1560], val_loss: 66.0683 Epoch [1580], val_loss: 65.6349 Epoch [1600], val_loss: 65.2186 Epoch [1620], val_loss: 64.8113 Epoch [1640], val_loss: 64.4109 Epoch [1660], val_loss: 64.0213 Epoch [1680], val_loss: 63.6375 Epoch [1700], val_loss: 63.2616 Epoch [1720], val_loss: 62.8886 Epoch [1740], val_loss: 62.5244 Epoch [1760], val_loss: 62.1691 Epoch [1780], val_loss: 61.8153 Epoch [1800], val_loss: 61.4625 Epoch [1820], val_loss: 61.1167 Epoch [1840], val_loss: 60.7700 Epoch [1860], val_loss: 60.4322 Epoch [1880], val_loss: 60.0954 Epoch [1900], val_loss: 59.7682 Epoch [1920], val_loss: 59.4436 Epoch [1940], val_loss: 59.1258 Epoch [1960], val_loss: 58.8162 Epoch [1980], val_loss: 58.5090 Epoch [2000], val_loss: 58.2042 Epoch [2020], val_loss: 57.9042 Epoch [2040], val_loss: 57.6124 Epoch [2060], val_loss: 57.3230 Epoch [2080], val_loss: 57.0376 Epoch [2100], val_loss: 56.7557 Epoch [2120], val_loss: 56.4770 Epoch [2140], val_loss: 56.2039 Epoch [2160], val_loss: 55.9361 Epoch [2180], val_loss: 55.6693 Epoch [2200], val_loss: 55.4074 Epoch [2220], val_loss: 55.1466 Epoch [2240], val_loss: 54.8878 Epoch [2260], val_loss: 54.6292 Epoch [2280], val_loss: 54.3750 Epoch [2300], val_loss: 54.1227 Epoch [2320], val_loss: 53.8744 Epoch [2340], val_loss: 53.6267 Epoch [2360], val_loss: 53.3828 Epoch [2380], val_loss: 53.1412 Epoch [2400], val_loss: 52.9009 Epoch [2420], val_loss: 52.6621 Epoch [2440], val_loss: 52.4289 Epoch [2460], val_loss: 52.1928 Epoch [2480], val_loss: 51.9618 Epoch [2500], val_loss: 51.7283 Epoch [2520], val_loss: 51.4984 Epoch [2540], val_loss: 51.2748 Epoch [2560], val_loss: 51.0513 Epoch [2580], val_loss: 50.8268 Epoch [2600], val_loss: 50.6023 Epoch [2620], val_loss: 50.3835 Epoch [2640], val_loss: 50.1650 Epoch [2660], val_loss: 49.9485 Epoch [2680], val_loss: 49.7333 Epoch [2700], val_loss: 49.5196 Epoch [2720], val_loss: 49.3078 Epoch [2740], val_loss: 49.1013 Epoch [2760], val_loss: 48.8960 Epoch [2780], val_loss: 48.6914 Epoch [2800], val_loss: 48.4893 Epoch [2820], val_loss: 48.2875 Epoch [2840], val_loss: 48.0885 Epoch [2860], val_loss: 47.8879 Epoch [2880], val_loss: 47.6917 Epoch [2900], val_loss: 47.4991 Epoch [2920], val_loss: 47.3073 Epoch [2940], val_loss: 47.1172 Epoch [2960], val_loss: 46.9274 Epoch [2980], val_loss: 46.7415 Epoch [3000], val_loss: 46.5568 Epoch [3020], val_loss: 46.3738 Epoch [3040], val_loss: 46.1903 Epoch [3060], val_loss: 46.0066 Epoch [3080], val_loss: 45.8263 Epoch [3100], val_loss: 45.6484 Epoch [3120], val_loss: 45.4715 Epoch [3140], val_loss: 45.2932 Epoch [3160], val_loss: 45.1209 Epoch [3180], val_loss: 44.9480 Epoch [3200], val_loss: 44.7778 Epoch [3220], val_loss: 44.6100 Epoch [3240], val_loss: 44.4426 Epoch [3260], val_loss: 44.2775 Epoch [3280], val_loss: 44.1107 Epoch [3300], val_loss: 43.9465 Epoch [3320], val_loss: 43.7830 Epoch [3340], val_loss: 43.6219 Epoch [3360], val_loss: 43.4628 Epoch [3380], val_loss: 43.3090 Epoch [3400], val_loss: 43.1527 Epoch [3420], val_loss: 42.9983 Epoch [3440], val_loss: 42.8429 Epoch [3460], val_loss: 42.6905 Epoch [3480], val_loss: 42.5400 Epoch [3500], val_loss: 42.3902 Epoch [3520], val_loss: 42.2446 Epoch [3540], val_loss: 42.0959 Epoch [3560], val_loss: 41.9500 Epoch [3580], val_loss: 41.8042 Epoch [3600], val_loss: 41.6592 Epoch [3620], val_loss: 41.5125 Epoch [3640], val_loss: 41.3654 Epoch [3660], val_loss: 41.2251 Epoch [3680], val_loss: 41.0858 Epoch [3700], val_loss: 40.9496 Epoch [3720], val_loss: 40.8140 Epoch [3740], val_loss: 40.6774 Epoch [3760], val_loss: 40.5418 Epoch [3780], val_loss: 40.4075 Epoch [3800], val_loss: 40.2739 Epoch [3820], val_loss: 40.1446 Epoch [3840], val_loss: 40.0137 Epoch [3860], val_loss: 39.8832 Epoch [3880], val_loss: 39.7547 Epoch [3900], val_loss: 39.6299 Epoch [3920], val_loss: 39.5082 Epoch [3940], val_loss: 39.3888 Epoch [3960], val_loss: 39.2663 Epoch [3980], val_loss: 39.1432 Epoch [4000], val_loss: 39.0190 Epoch [4020], val_loss: 38.8972 Epoch [4040], val_loss: 38.7766 Epoch [4060], val_loss: 38.6564 Epoch [4080], val_loss: 38.5384 Epoch [4100], val_loss: 38.4248 Epoch [4120], val_loss: 38.3128 Epoch [4140], val_loss: 38.2014 Epoch [4160], val_loss: 38.0890 Epoch [4180], val_loss: 37.9782 Epoch [4200], val_loss: 37.8654 Epoch [4220], val_loss: 37.7563 Epoch [4240], val_loss: 37.6506 Epoch [4260], val_loss: 37.5399 Epoch [4280], val_loss: 37.4337 Epoch [4300], val_loss: 37.3292 Epoch [4320], val_loss: 37.2244 Epoch [4340], val_loss: 37.1226 Epoch [4360], val_loss: 37.0204 Epoch [4380], val_loss: 36.9182 Epoch [4400], val_loss: 36.8143 Epoch [4420], val_loss: 36.7139 Epoch [4440], val_loss: 36.6116 Epoch [4460], val_loss: 36.5138 Epoch [4480], val_loss: 36.4173 Epoch [4500], val_loss: 36.3202 Epoch [4520], val_loss: 36.2234 Epoch [4540], val_loss: 36.1261 Epoch [4560], val_loss: 36.0294 Epoch [4580], val_loss: 35.9293 Epoch [4600], val_loss: 35.8356 Epoch [4620], val_loss: 35.7423 Epoch [4640], val_loss: 35.6513 Epoch [4660], val_loss: 35.5569 Epoch [4680], val_loss: 35.4668 Epoch [4700], val_loss: 35.3746 Epoch [4720], val_loss: 35.2827 Epoch [4740], val_loss: 35.1934 Epoch [4760], val_loss: 35.1064 Epoch [4780], val_loss: 35.0194 Epoch [4800], val_loss: 34.9304 Epoch [4820], val_loss: 34.8422 Epoch [4840], val_loss: 34.7542 Epoch [4860], val_loss: 34.6696 Epoch [4880], val_loss: 34.5848 Epoch [4900], val_loss: 34.5001 Epoch [4920], val_loss: 34.4157 Epoch [4940], val_loss: 34.3328 Epoch [4960], val_loss: 34.2509 Epoch [4980], val_loss: 34.1690 Epoch [5000], val_loss: 34.0866 Epoch [5020], val_loss: 34.0061 Epoch [5040], val_loss: 33.9243 Epoch [5060], val_loss: 33.8443 Epoch [5080], val_loss: 33.7660 Epoch [5100], val_loss: 33.6874 Epoch [5120], val_loss: 33.6124 Epoch [5140], val_loss: 33.5367
Epoch [5160], val_loss: 33.4589 Epoch [5180], val_loss: 33.3838 Epoch [5200], val_loss: 33.3089 Epoch [5220], val_loss: 33.2336 Epoch [5240], val_loss: 33.1614 Epoch [5260], val_loss: 33.0905 Epoch [5280], val_loss: 33.0170 Epoch [5300], val_loss: 32.9438 Epoch [5320], val_loss: 32.8763 Epoch [5340], val_loss: 32.8063 Epoch [5360], val_loss: 32.7362 Epoch [5380], val_loss: 32.6694 Epoch [5400], val_loss: 32.6019 Epoch [5420], val_loss: 32.5341 Epoch [5440], val_loss: 32.4694 Epoch [5460], val_loss: 32.4049 Epoch [5480], val_loss: 32.3405 Epoch [5500], val_loss: 32.2771 Epoch [5520], val_loss: 32.2153 Epoch [5540], val_loss: 32.1529 Epoch [5560], val_loss: 32.0919 Epoch [5580], val_loss: 32.0322 Epoch [5600], val_loss: 31.9704 Epoch [5620], val_loss: 31.9095 Epoch [5640], val_loss: 31.8514 Epoch [5660], val_loss: 31.7912 Epoch [5680], val_loss: 31.7336 Epoch [5700], val_loss: 31.6767 Epoch [5720], val_loss: 31.6217 Epoch [5740], val_loss: 31.5641 Epoch [5760], val_loss: 31.5118 Epoch [5780], val_loss: 31.4583 Epoch [5800], val_loss: 31.4028 Epoch [5820], val_loss: 31.3528 Epoch [5840], val_loss: 31.3014 Epoch [5860], val_loss: 31.2499 Epoch [5880], val_loss: 31.2009 Epoch [5900], val_loss: 31.1549 Epoch [5920], val_loss: 31.1023 Epoch [5940], val_loss: 31.0546 Epoch [5960], val_loss: 31.0036 Epoch [5980], val_loss: 30.9581 Epoch [6000], val_loss: 30.9095 Epoch [6020], val_loss: 30.8599 Epoch [6040], val_loss: 30.8082 Epoch [6060], val_loss: 30.7589 Epoch [6080], val_loss: 30.7074 Epoch [6100], val_loss: 30.6615 Epoch [6120], val_loss: 30.6145 Epoch [6140], val_loss: 30.5695 Epoch [6160], val_loss: 30.5245 Epoch [6180], val_loss: 30.4785 Epoch [6200], val_loss: 30.4303 Epoch [6220], val_loss: 30.3885 Epoch [6240], val_loss: 30.3482 Epoch [6260], val_loss: 30.3043 Epoch [6280], val_loss: 30.2588 Epoch [6300], val_loss: 30.2159 Epoch [6320], val_loss: 30.1721 Epoch [6340], val_loss: 30.1310 Epoch [6360], val_loss: 30.0906 Epoch [6380], val_loss: 30.0535 Epoch [6400], val_loss: 30.0119 Epoch [6420], val_loss: 29.9732 Epoch [6440], val_loss: 29.9321 Epoch [6460], val_loss: 29.8927 Epoch [6480], val_loss: 29.8512 Epoch [6500], val_loss: 29.8120 Epoch [6520], val_loss: 29.7769 Epoch [6540], val_loss: 29.7387 Epoch [6560], val_loss: 29.7056 Epoch [6580], val_loss: 29.6656 Epoch [6600], val_loss: 29.6290 Epoch [6620], val_loss: 29.5912 Epoch [6640], val_loss: 29.5558 Epoch [6660], val_loss: 29.5193 Epoch [6680], val_loss: 29.4848 Epoch [6700], val_loss: 29.4483 Epoch [6720], val_loss: 29.4114 Epoch [6740], val_loss: 29.3736 Epoch [6760], val_loss: 29.3353 Epoch [6780], val_loss: 29.3029 Epoch [6800], val_loss: 29.2683 Epoch [6820], val_loss: 29.2335 Epoch [6840], val_loss: 29.2000 Epoch [6860], val_loss: 29.1657 Epoch [6880], val_loss: 29.1359 Epoch [6900], val_loss: 29.1033 Epoch [6920], val_loss: 29.0722 Epoch [6940], val_loss: 29.0409 Epoch [6960], val_loss: 29.0108 Epoch [6980], val_loss: 28.9772 Epoch [7000], val_loss: 28.9444 Epoch [7020], val_loss: 28.9111 Epoch [7040], val_loss: 28.8809 Epoch [7060], val_loss: 28.8472 Epoch [7080], val_loss: 28.8160 Epoch [7100], val_loss: 28.7831 Epoch [7120], val_loss: 28.7484 Epoch [7140], val_loss: 28.7199 Epoch [7160], val_loss: 28.6929 Epoch [7180], val_loss: 28.6602 Epoch [7200], val_loss: 28.6293 Epoch [7220], val_loss: 28.6009 Epoch [7240], val_loss: 28.5735 Epoch [7260], val_loss: 28.5426 Epoch [7280], val_loss: 28.5166 Epoch [7300], val_loss: 28.4892 Epoch [7320], val_loss: 28.4578 Epoch [7340], val_loss: 28.4312 Epoch [7360], val_loss: 28.4036 Epoch [7380], val_loss: 28.3758 Epoch [7400], val_loss: 28.3492 Epoch [7420], val_loss: 28.3228 Epoch [7440], val_loss: 28.2964 Epoch [7460], val_loss: 28.2698 Epoch [7480], val_loss: 28.2402 Epoch [7500], val_loss: 28.2157 Epoch [7520], val_loss: 28.1882 Epoch [7540], val_loss: 28.1638 Epoch [7560], val_loss: 28.1383 Epoch [7580], val_loss: 28.1131 Epoch [7600], val_loss: 28.0850 Epoch [7620], val_loss: 28.0621 Epoch [7640], val_loss: 28.0343 Epoch [7660], val_loss: 28.0103 Epoch [7680], val_loss: 27.9855 Epoch [7700], val_loss: 27.9617 Epoch [7720], val_loss: 27.9384 Epoch [7740], val_loss: 27.9159 Epoch [7760], val_loss: 27.8909 Epoch [7780], val_loss: 27.8669 Epoch [7800], val_loss: 27.8429 Epoch [7820], val_loss: 27.8191 Epoch [7840], val_loss: 27.7985 Epoch [7860], val_loss: 27.7758 Epoch [7880], val_loss: 27.7545 Epoch [7900], val_loss: 27.7320 Epoch [7920], val_loss: 27.7122 Epoch [7940], val_loss: 27.6894 Epoch [7960], val_loss: 27.6694 Epoch [7980], val_loss: 27.6444 Epoch [8000], val_loss: 27.6219 Epoch [8020], val_loss: 27.6024 Epoch [8040], val_loss: 27.5774 Epoch [8060], val_loss: 27.5532 Epoch [8080], val_loss: 27.5328 Epoch [8100], val_loss: 27.5121 Epoch [8120], val_loss: 27.4917 Epoch [8140], val_loss: 27.4691 Epoch [8160], val_loss: 27.4468 Epoch [8180], val_loss: 27.4269 Epoch [8200], val_loss: 27.4008 Epoch [8220], val_loss: 27.3785 Epoch [8240], val_loss: 27.3576 Epoch [8260], val_loss: 27.3410 Epoch [8280], val_loss: 27.3169 Epoch [8300], val_loss: 27.2955 Epoch [8320], val_loss: 27.2743 Epoch [8340], val_loss: 27.2532 Epoch [8360], val_loss: 27.2345 Epoch [8380], val_loss: 27.2151 Epoch [8400], val_loss: 27.1938 Epoch [8420], val_loss: 27.1746 Epoch [8440], val_loss: 27.1538 Epoch [8460], val_loss: 27.1386 Epoch [8480], val_loss: 27.1199 Epoch [8500], val_loss: 27.0980 Epoch [8520], val_loss: 27.0825 Epoch [8540], val_loss: 27.0642 Epoch [8560], val_loss: 27.0448 Epoch [8580], val_loss: 27.0264 Epoch [8600], val_loss: 27.0068 Epoch [8620], val_loss: 26.9892 Epoch [8640], val_loss: 26.9706 Epoch [8660], val_loss: 26.9511 Epoch [8680], val_loss: 26.9284 Epoch [8700], val_loss: 26.9148 Epoch [8720], val_loss: 26.8953 Epoch [8740], val_loss: 26.8755 Epoch [8760], val_loss: 26.8555 Epoch [8780], val_loss: 26.8378 Epoch [8800], val_loss: 26.8202 Epoch [8820], val_loss: 26.8045 Epoch [8840], val_loss: 26.7845 Epoch [8860], val_loss: 26.7694 Epoch [8880], val_loss: 26.7506 Epoch [8900], val_loss: 26.7336 Epoch [8920], val_loss: 26.7153 Epoch [8940], val_loss: 26.6963 Epoch [8960], val_loss: 26.6770 Epoch [8980], val_loss: 26.6584 Epoch [9000], val_loss: 26.6411 Epoch [9020], val_loss: 26.6275 Epoch [9040], val_loss: 26.6078 Epoch [9060], val_loss: 26.5922 Epoch [9080], val_loss: 26.5745 Epoch [9100], val_loss: 26.5566 Epoch [9120], val_loss: 26.5395 Epoch [9140], val_loss: 26.5225 Epoch [9160], val_loss: 26.5062 Epoch [9180], val_loss: 26.4895 Epoch [9200], val_loss: 26.4722 Epoch [9220], val_loss: 26.4560 Epoch [9240], val_loss: 26.4396 Epoch [9260], val_loss: 26.4237 Epoch [9280], val_loss: 26.4072 Epoch [9300], val_loss: 26.3914 Epoch [9320], val_loss: 26.3762 Epoch [9340], val_loss: 26.3592 Epoch [9360], val_loss: 26.3469 Epoch [9380], val_loss: 26.3338 Epoch [9400], val_loss: 26.3135 Epoch [9420], val_loss: 26.3017 Epoch [9440], val_loss: 26.2841 Epoch [9460], val_loss: 26.2682 Epoch [9480], val_loss: 26.2498 Epoch [9500], val_loss: 26.2371 Epoch [9520], val_loss: 26.2212 Epoch [9540], val_loss: 26.1998 Epoch [9560], val_loss: 26.1875 Epoch [9580], val_loss: 26.1695 Epoch [9600], val_loss: 26.1567 Epoch [9620], val_loss: 26.1404 Epoch [9640], val_loss: 26.1251 Epoch [9660], val_loss: 26.1093 Epoch [9680], val_loss: 26.0913 Epoch [9700], val_loss: 26.0775 Epoch [9720], val_loss: 26.0592 Epoch [9740], val_loss: 26.0465 Epoch [9760], val_loss: 26.0324 Epoch [9780], val_loss: 26.0163 Epoch [9800], val_loss: 25.9986 Epoch [9820], val_loss: 25.9815 Epoch [9840], val_loss: 25.9682 Epoch [9860], val_loss: 25.9530 Epoch [9880], val_loss: 25.9371 Epoch [9900], val_loss: 25.9239 Epoch [9920], val_loss: 25.9089 Epoch [9940], val_loss: 25.8958 Epoch [9960], val_loss: 25.8781 Epoch [9980], val_loss: 25.8675 Epoch [10000], val_loss: 25.8515
In [86]:
losses = [r['val_loss'] for r in [result] + history]
plt.plot(losses, '-x')
plt.xlabel('epoch')
plt.ylabel('val_loss')
plt.title('val_loss vs. epochs');
Notebook Image

Prediction

In [87]:
def predict_single(x, model):
    xb = x.unsqueeze(0)
    return model(x).item()
In [89]:
x, target = val_ds[10]
pred = predict_single(x, model)
print("Input: ", x)
print("Target: ", target.item())
print("Prediction:", pred)
Input: tensor([ 6.1000e+00, 1.4580e+03, -2.0000e+02, 2.0400e+01, 1.3070e+03, 7.0600e+02, 4.9700e+02, 1.6500e+02, 1.4830e+03, 2.1030e+03, 6.1000e+00, 5.7190e-01, 2.4000e+01, 1.2000e+01, 2.0040e+03, 9.0000e+00]) Target: 60.5 Prediction: 78.63116455078125

Save and upload

In [90]:
torch.save(model.state_dict(), 'air-quality-linear-minimal.pth')
In [91]:
val_loss = [result] + history
In [92]:
jovian.log_metrics(val_loss=val_loss)
[jovian] Metrics logged.
In [ ]:
jovian.commit(project='air-quality-linear-minimal', environment=None, outputs=['air-quality-linear-minimal.pth'])
jovian.commit(project='air-quality-linear-minimal', environment=None, outputs=['air-quality-linear-minimal.pth']) # Kaggle commit fails sometimes, so try again..
[jovian] Attempting to save notebook.. [jovian] Updating notebook "khinthandarkyaw98/air-quality-linear-minimal" on https://jovian.ml/ [jovian] Uploading notebook.. [jovian] Uploading additional outputs... [jovian] Attaching records (metrics, hyperparameters, dataset etc.) [jovian] Committed successfully! https://jovian.ml/khinthandarkyaw98/air-quality-linear-minimal
[jovian] Attempting to save notebook..
In [ ]: