Building energy efficiency prediction

Energy efficiency preiction model using fully conected neural network.

In this tutorial, we’ll construct simple fully-connected neural networks to building energy efficiency analysis. Here we predict heating-load of from each building features, such as wall-area or glazing-area. Please download the data from UCI website in advance ( https://archive.ics.uci.edu/ml/datasets/Energy+efficiency ).

Required libraries

In [1]:
%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split

import renom as rm
from renom import Sequential
from renom import Dense, Relu, Tanh
from renom import Adam

Load & preprocess the data

In [2]:
df = pd.read_csv('../dataset/energyeff.csv')

Now, we standardize the data in each column and convert it to a numpy array.

In [3]:
df_s = df.copy()

for col in df.columns:
    v_std = df[col].std()
    v_mean = df[col].mean()
    df_s[col] = (df_s[col] - v_mean) / v_std
In [4]:
df_s.head()
Out[4]:
RelativeCompactness SurfaceArea WallArea RoofArea OverallArea Orientation GlazingArea GlazingAreaDistribution HeatingLoad CoolingLoad
0 2.040447 -1.784712 -0.561586 -1.469119 0.999349 -1.340767 -1.7593 -1.813393 -0.669680 -0.342443
1 2.040447 -1.784712 -0.561586 -1.469119 0.999349 -0.446922 -1.7593 -1.813393 -0.669680 -0.342443
2 2.040447 -1.784712 -0.561586 -1.469119 0.999349 0.446922 -1.7593 -1.813393 -0.669680 -0.342443
3 2.040447 -1.784712 -0.561586 -1.469119 0.999349 1.340767 -1.7593 -1.813393 -0.669680 -0.342443
4 1.284142 -1.228438 0.000000 -1.197897 0.999349 -1.340767 -1.7593 -1.813393 -0.145409 0.388113
In [5]:
X, y = np.array(df_s.iloc[:, :8]), np.array(df_s.iloc[:, 8:])
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=1)

Definition of a nural network with sequential model

In [6]:
model = Sequential([
    Dense(5),
    Tanh(),
    Dense(3),
    Relu(),
    Dense(1)
])

Define an optimizer function

In [7]:
optimizer = Adam()

Training loop for heating-load regression

In the training loop, we recommend split train data into train and validation data for cross-validation.

In [8]:
# Hyper parameters
EPOCH = 1000 # Number of epochs
BATCH = 64 # Mini-batch size

# Learning curves
learning_curve = []
val_curve = []

# Training loop
for i in range(EPOCH):
    # split training data into train and validation data
    X_train_, X_val, y_train_, y_val = train_test_split(X_train, y_train, test_size=0.1)

    N = X_train_.shape[0] # Number of records in training data
    perm = np.random.permutation(N)
    train_loss = 0

    for j in range(N//BATCH):
        # Make mini-batch
        index = perm[j*BATCH:(j+1)*BATCH]
        train_batch_x = X_train_[index]
        train_batch_y = y_train_[index]

        # Forward propagation
        with model.train():
            z = model(train_batch_x)
            loss = rm.mean_squared_error(z, train_batch_y)

        # Backpropagation
        grad = loss.grad()

        # Update
        grad.update(optimizer)

        train_loss += loss.as_ndarray()

    # calculate mean squared error for training data
    train_loss = train_loss / (N // BATCH)
    learning_curve.append(train_loss)

    # calculate mean squared error for validation data
    y_val_pred = model(X_val)
    val_loss = rm.mean_squared_error(y_val_pred, y_val).as_ndarray()
    val_curve.append(val_loss)

    # print training progress
    if i % 50 == 0:
        print("Epoch %d - loss: %f - val_loss: %f" % (i, train_loss, val_loss))

print('Finished!')
Epoch 0 - loss: 0.901171 - val_loss: 0.852024
Epoch 50 - loss: 0.174472 - val_loss: 0.158919
Epoch 100 - loss: 0.094337 - val_loss: 0.107187
Epoch 150 - loss: 0.088355 - val_loss: 0.055800
Epoch 200 - loss: 0.078017 - val_loss: 0.076747
Epoch 250 - loss: 0.068304 - val_loss: 0.056301
Epoch 300 - loss: 0.056930 - val_loss: 0.058698
Epoch 350 - loss: 0.048034 - val_loss: 0.052798
Epoch 400 - loss: 0.039590 - val_loss: 0.039310
Epoch 450 - loss: 0.035393 - val_loss: 0.029911
Epoch 500 - loss: 0.029567 - val_loss: 0.039718
Epoch 550 - loss: 0.028464 - val_loss: 0.026045
Epoch 600 - loss: 0.025263 - val_loss: 0.034021
Epoch 650 - loss: 0.024738 - val_loss: 0.023805
Epoch 700 - loss: 0.023383 - val_loss: 0.019178
Epoch 750 - loss: 0.020792 - val_loss: 0.025845
Epoch 800 - loss: 0.021659 - val_loss: 0.022081
Epoch 850 - loss: 0.019500 - val_loss: 0.025580
Epoch 900 - loss: 0.019716 - val_loss: 0.021059
Epoch 950 - loss: 0.019920 - val_loss: 0.019543
Finished!

Model evaluation

Let’s evaluate the fitted model!

Plot learning curve

In [9]:
plt.figure(figsize=(10, 4))
plt.plot(learning_curve, label='loss')
plt.plot(val_curve, label='val_loss')
plt.title('Learning curve')
plt.xlabel("Epoch")
plt.ylabel("MSE")
plt.legend()
plt.grid()
../../../_images/notebooks_regression_energyefficiency_notebook_18_0.png

Compare the actual and predicted heating-load

In [11]:
# predict test value
y_pred = model(X_test)

plt.figure(figsize=(8, 8))
plt.plot([-1.5, 2.5], [-1.5, 2.5], c='k', alpha=0.6)
plt.scatter(y_test[:, 0].reshape(-1, 1), y_pred)
plt.xlim(-1.5, 2.5)
plt.ylim(-1.5, 2.5)
plt.xlabel('Standardized Actual Heating Load', fontsize=16)
plt.ylabel('Standardized Predicted Heating Load', fontsize=16)
plt.grid()
../../../_images/notebooks_regression_energyefficiency_notebook_20_0.png