Nathaniel Dake Blog

16. Facial Expression Recognition - TensorFlow

We are now going to go through the facial expression recognition project that we have worked on in the past, but we will use TensorFlow as our framework of choice this time! We will be creating a neural network that has 2000 units in the first hidden layer, and 1000 units in the second hidden layer. We can start with our imports.

In [1]:
from __future__ import print_function, division
from builtins import range

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from sklearn.utils import shuffle
% matplotlib inline

"""----------------------- Function to get data -----------------------------"""
def getData(balance_ones=True):
    # images are 48x48 = 2304 size vectors
    Y = []
    X = []
    first = True
    for line in open('../../../data/fer/fer2013.csv'):
        if first:
            first = False
        else:
            row = line.split(',')
            Y.append(int(row[0]))
            X.append([int(p) for p in row[1].split()])

    X, Y = np.array(X) / 255.0, np.array(Y)

    if balance_ones:
        # balance the 1 class
        X0, Y0 = X[Y!=1, :], Y[Y!=1]
        X1 = X[Y==1, :]
        X1 = np.repeat(X1, 9, axis=0)
        X = np.vstack([X0, X1])
        Y = np.concatenate((Y0, [1]*len(X1)))

    return X, Y
  
""" --------- Creates indicator (N x K), from an input N x 1 y matrix --------"""
def y2indicator(y):
    N = len(y)
    K = len(set(y))
    ind = np.zeros((N, K))
    for i in range(N):
        ind[i, y[i]] = 1
    return ind
  
""" ----------- Gives the error rate between targets and predictions ---------------- """
def error_rate(targets, predictions):
    return np.mean(targets != predictions)
  
""" Rectifier Linear Unit - an activation function that can be used in a neural network """
def relu(x):
    return x * (x > 0)
  
"""
Function to initialize a weight matrix and a bias. M1 is the input size, and M2 is the output size
W is a matrix of size M1 x M2, which is randomized initialy to a gaussian normal
We make the standard deviation of this the sqrt of size in + size out
The bias is initialized as zeros. Each is then turned into float 32s so that they can be used in 
Theano and TensorFlow
"""
def init_weight_and_bias(M1, M2):
    W = np.random.randn(M1, M2) / np.sqrt(M1)
    b = np.zeros(M2)
    return W.astype(np.float32), b.astype(np.float32)



class HiddenLayer(object):
    def __init__(self, M1, M2, an_id):
        self.id = an_id
        self.M1 = M1
        self.M2 = M2
        W, b = init_weight_and_bias(M1, M2)
        self.W = tf.Variable(W.astype(np.float32))
        self.b = tf.Variable(b.astype(np.float32))
        self.params = [self.W, self.b]

    def forward(self, X):
        return tf.nn.relu(tf.matmul(X, self.W) + self.b)


class ANN(object):
    def __init__(self, hidden_layer_sizes):
        self.hidden_layer_sizes = hidden_layer_sizes

    def fit(self, X, Y, learning_rate=1e-2, mu=0.99, decay=0.999, reg=1e-3, epochs=10, batch_sz=100, show_fig=False):
        K = len(set(Y)) # won't work later b/c we turn it into indicator

        # make a validation set
        X, Y = shuffle(X, Y)
        X = X.astype(np.float32)
        Y = y2indicator(Y).astype(np.float32)
        # Y = Y.astype(np.int32)
        Xvalid, Yvalid = X[-1000:], Y[-1000:]
        Yvalid_flat = np.argmax(Yvalid, axis=1) # for calculating error rate
        X, Y = X[:-1000], Y[:-1000]

        # initialize hidden layers
        N, D = X.shape
        
        self.hidden_layers = []
        M1 = D
        count = 0
        for M2 in self.hidden_layer_sizes:
            h = HiddenLayer(M1, M2, count)
            self.hidden_layers.append(h)
            M1 = M2
            count += 1
        W, b = init_weight_and_bias(M1, K)
        self.W = tf.Variable(W.astype(np.float32))
        self.b = tf.Variable(b.astype(np.float32))

        # collect params for later use
        self.params = [self.W, self.b]
        for h in self.hidden_layers:
            self.params += h.params

        # set up theano functions and variables
        tfX = tf.placeholder(tf.float32, shape=(None, D), name='X')
        tfT = tf.placeholder(tf.float32, shape=(None, K), name='T')
        act = self.forward(tfX)

        rcost = reg*sum([tf.nn.l2_loss(p) for p in self.params])
        cost = tf.reduce_mean(
            tf.nn.softmax_cross_entropy_with_logits(
                logits=act,
                labels=tfT
            )
        ) + rcost
        prediction = self.predict(tfX)
        train_op = tf.train.RMSPropOptimizer(learning_rate, decay=decay, momentum=mu).minimize(cost)

        n_batches = N // batch_sz
        costs = []
        init = tf.global_variables_initializer()
        with tf.Session() as session:
            session.run(init)
            for i in range(epochs):
                X, Y = shuffle(X, Y)
                for j in range(n_batches):
                    Xbatch = X[j*batch_sz:(j*batch_sz+batch_sz)]
                    Ybatch = Y[j*batch_sz:(j*batch_sz+batch_sz)]

                    session.run(train_op, feed_dict={tfX: Xbatch, tfT: Ybatch})

                    if j % 20 == 0:
                        c = session.run(cost, feed_dict={tfX: Xvalid, tfT: Yvalid})
                        costs.append(c)

                        p = session.run(prediction, feed_dict={tfX: Xvalid, tfT: Yvalid})
                        e = error_rate(Yvalid_flat, p)
                        print("i:", i, "j:", j, "nb:", n_batches, "cost:", c, "error rate:", e)
        
        if show_fig:
            plt.plot(costs)
            plt.show()

    def forward(self, X):
        Z = X
        for h in self.hidden_layers:
            Z = h.forward(Z)
        return tf.matmul(Z, self.W) + self.b

    def predict(self, X):
        act = self.forward(X)
        return tf.argmax(act, 1)


def main():
    X, Y = getData()
    # X, Y = getBinaryData()
    model = ANN([2000, 1000, 500])
    model.fit(X, Y, show_fig=True)

if __name__ == '__main__':
    main()
WARNING:tensorflow:From <ipython-input-1-90d4eb09fced>:125: softmax_cross_entropy_with_logits (from tensorflow.python.ops.nn_ops) is deprecated and will be removed in a future version.
Instructions for updating:

Future major versions of TensorFlow will allow gradients to flow
into the labels input on backprop by default.

See tf.nn.softmax_cross_entropy_with_logits_v2.

i: 0 j: 0 nb: 392 cost: 3.7444239 error rate: 0.896
i: 0 j: 20 nb: 392 cost: 3.6486535 error rate: 0.76
i: 0 j: 40 nb: 392 cost: 3.6617503 error rate: 0.814
i: 0 j: 60 nb: 392 cost: 3.6052442 error rate: 0.775
i: 0 j: 80 nb: 392 cost: 3.550693 error rate: 0.768
i: 0 j: 100 nb: 392 cost: 3.5379243 error rate: 0.824
i: 0 j: 120 nb: 392 cost: 3.4323988 error rate: 0.719
i: 0 j: 140 nb: 392 cost: 3.4212375 error rate: 0.736
i: 0 j: 160 nb: 392 cost: 3.4390187 error rate: 0.798
i: 0 j: 180 nb: 392 cost: 3.2884684 error rate: 0.727
i: 0 j: 200 nb: 392 cost: 3.2441034 error rate: 0.726
i: 0 j: 220 nb: 392 cost: 3.2461233 error rate: 0.735
i: 0 j: 240 nb: 392 cost: 3.1861126 error rate: 0.735
i: 0 j: 260 nb: 392 cost: 3.0890884 error rate: 0.737
i: 0 j: 280 nb: 392 cost: 3.038301 error rate: 0.703
i: 0 j: 300 nb: 392 cost: 3.0107286 error rate: 0.715
i: 0 j: 320 nb: 392 cost: 2.9454527 error rate: 0.71
i: 0 j: 340 nb: 392 cost: 2.9790137 error rate: 0.768
i: 0 j: 360 nb: 392 cost: 2.8908274 error rate: 0.733
i: 0 j: 380 nb: 392 cost: 2.8120208 error rate: 0.712
i: 1 j: 0 nb: 392 cost: 2.8223603 error rate: 0.767
i: 1 j: 20 nb: 392 cost: 2.7929351 error rate: 0.737
i: 1 j: 40 nb: 392 cost: 2.733191 error rate: 0.732
i: 1 j: 60 nb: 392 cost: 2.7044168 error rate: 0.731
i: 1 j: 80 nb: 392 cost: 2.691378 error rate: 0.736
i: 1 j: 100 nb: 392 cost: 2.6382952 error rate: 0.745
i: 1 j: 120 nb: 392 cost: 2.5975192 error rate: 0.72
i: 1 j: 140 nb: 392 cost: 2.6334476 error rate: 0.747
i: 1 j: 160 nb: 392 cost: 2.565466 error rate: 0.758
i: 1 j: 180 nb: 392 cost: 2.569295 error rate: 0.772
i: 1 j: 200 nb: 392 cost: 2.496163 error rate: 0.763
i: 1 j: 220 nb: 392 cost: 2.4612014 error rate: 0.717
i: 1 j: 240 nb: 392 cost: 2.4175649 error rate: 0.707
i: 1 j: 260 nb: 392 cost: 2.3886244 error rate: 0.706
i: 1 j: 280 nb: 392 cost: 2.3597152 error rate: 0.722
i: 1 j: 300 nb: 392 cost: 2.3148081 error rate: 0.706
i: 1 j: 320 nb: 392 cost: 2.2981434 error rate: 0.718
i: 1 j: 340 nb: 392 cost: 2.304362 error rate: 0.74
i: 1 j: 360 nb: 392 cost: 2.315434 error rate: 0.751
i: 1 j: 380 nb: 392 cost: 2.2772954 error rate: 0.737
i: 2 j: 0 nb: 392 cost: 2.256354 error rate: 0.736
i: 2 j: 20 nb: 392 cost: 2.2296686 error rate: 0.727
i: 2 j: 40 nb: 392 cost: 2.2834866 error rate: 0.765
i: 2 j: 60 nb: 392 cost: 2.272914 error rate: 0.75
i: 2 j: 80 nb: 392 cost: 2.1735055 error rate: 0.715
i: 2 j: 100 nb: 392 cost: 2.259664 error rate: 0.806
i: 2 j: 120 nb: 392 cost: 2.1914234 error rate: 0.756
i: 2 j: 140 nb: 392 cost: 2.150073 error rate: 0.717
i: 2 j: 160 nb: 392 cost: 2.1095958 error rate: 0.722
i: 2 j: 180 nb: 392 cost: 2.1167293 error rate: 0.73
i: 2 j: 200 nb: 392 cost: 2.1377192 error rate: 0.745
i: 2 j: 220 nb: 392 cost: 2.0978484 error rate: 0.748
i: 2 j: 240 nb: 392 cost: 2.0721645 error rate: 0.726
i: 2 j: 260 nb: 392 cost: 2.12414 error rate: 0.755
i: 2 j: 280 nb: 392 cost: 2.0796068 error rate: 0.776
i: 2 j: 300 nb: 392 cost: 2.0351427 error rate: 0.721
i: 2 j: 320 nb: 392 cost: 2.0546637 error rate: 0.753
i: 2 j: 340 nb: 392 cost: 2.0564437 error rate: 0.749
i: 2 j: 360 nb: 392 cost: 2.0326996 error rate: 0.71
i: 2 j: 380 nb: 392 cost: 2.0992327 error rate: 0.761
i: 3 j: 0 nb: 392 cost: 2.0470243 error rate: 0.749
i: 3 j: 20 nb: 392 cost: 2.0239136 error rate: 0.735
i: 3 j: 40 nb: 392 cost: 2.002708 error rate: 0.726
i: 3 j: 60 nb: 392 cost: 1.9782068 error rate: 0.713
i: 3 j: 80 nb: 392 cost: 1.9654258 error rate: 0.71
i: 3 j: 100 nb: 392 cost: 1.940547 error rate: 0.712
i: 3 j: 120 nb: 392 cost: 1.969008 error rate: 0.742
i: 3 j: 140 nb: 392 cost: 1.9489187 error rate: 0.709
i: 3 j: 160 nb: 392 cost: 1.9703429 error rate: 0.721
i: 3 j: 180 nb: 392 cost: 2.0305126 error rate: 0.758
i: 3 j: 200 nb: 392 cost: 1.9861485 error rate: 0.736
i: 3 j: 220 nb: 392 cost: 1.9523468 error rate: 0.741
i: 3 j: 240 nb: 392 cost: 1.9645606 error rate: 0.76
i: 3 j: 260 nb: 392 cost: 1.9103469 error rate: 0.715
i: 3 j: 280 nb: 392 cost: 2.0297978 error rate: 0.755
i: 3 j: 300 nb: 392 cost: 1.9951283 error rate: 0.76
i: 3 j: 320 nb: 392 cost: 1.9735472 error rate: 0.759
i: 3 j: 340 nb: 392 cost: 1.9544493 error rate: 0.73
i: 3 j: 360 nb: 392 cost: 1.9519062 error rate: 0.735
i: 3 j: 380 nb: 392 cost: 1.9449747 error rate: 0.732
i: 4 j: 0 nb: 392 cost: 1.9427075 error rate: 0.725
i: 4 j: 20 nb: 392 cost: 1.9717175 error rate: 0.763
i: 4 j: 40 nb: 392 cost: 1.9420954 error rate: 0.738
i: 4 j: 60 nb: 392 cost: 1.9680127 error rate: 0.734
i: 4 j: 80 nb: 392 cost: 1.9839851 error rate: 0.779
i: 4 j: 100 nb: 392 cost: 1.958307 error rate: 0.727
i: 4 j: 120 nb: 392 cost: 1.9560182 error rate: 0.77
i: 4 j: 140 nb: 392 cost: 1.9605316 error rate: 0.734
i: 4 j: 160 nb: 392 cost: 1.94503 error rate: 0.763
i: 4 j: 180 nb: 392 cost: 1.9394308 error rate: 0.74
i: 4 j: 200 nb: 392 cost: 1.9190239 error rate: 0.725
i: 4 j: 220 nb: 392 cost: 1.933627 error rate: 0.743
i: 4 j: 240 nb: 392 cost: 1.9453828 error rate: 0.749
i: 4 j: 260 nb: 392 cost: 1.9282091 error rate: 0.734
i: 4 j: 280 nb: 392 cost: 1.9232643 error rate: 0.743
i: 4 j: 300 nb: 392 cost: 1.9124113 error rate: 0.743
i: 4 j: 320 nb: 392 cost: 1.9025718 error rate: 0.721
i: 4 j: 340 nb: 392 cost: 1.9422108 error rate: 0.758
i: 4 j: 360 nb: 392 cost: 1.9190676 error rate: 0.751
i: 4 j: 380 nb: 392 cost: 1.9182011 error rate: 0.746
i: 5 j: 0 nb: 392 cost: 1.974688 error rate: 0.827
i: 5 j: 20 nb: 392 cost: 1.9138955 error rate: 0.756
i: 5 j: 40 nb: 392 cost: 1.9603482 error rate: 0.77
i: 5 j: 60 nb: 392 cost: 1.9148173 error rate: 0.759
i: 5 j: 80 nb: 392 cost: 1.9497594 error rate: 0.797
i: 5 j: 100 nb: 392 cost: 1.962197 error rate: 0.848
i: 5 j: 120 nb: 392 cost: 1.9305347 error rate: 0.76
i: 5 j: 140 nb: 392 cost: 1.9297981 error rate: 0.754
i: 5 j: 160 nb: 392 cost: 1.9028724 error rate: 0.754
i: 5 j: 180 nb: 392 cost: 1.9358066 error rate: 0.77
i: 5 j: 200 nb: 392 cost: 1.9100628 error rate: 0.731
i: 5 j: 220 nb: 392 cost: 1.9096744 error rate: 0.75
i: 5 j: 240 nb: 392 cost: 1.9552962 error rate: 0.745
i: 5 j: 260 nb: 392 cost: 1.9470583 error rate: 0.835
i: 5 j: 280 nb: 392 cost: 1.9638418 error rate: 0.764
i: 5 j: 300 nb: 392 cost: 1.9295757 error rate: 0.76
i: 5 j: 320 nb: 392 cost: 1.923968 error rate: 0.719
i: 5 j: 340 nb: 392 cost: 1.9413893 error rate: 0.784
i: 5 j: 360 nb: 392 cost: 1.913671 error rate: 0.734
i: 5 j: 380 nb: 392 cost: 1.8847265 error rate: 0.737
i: 6 j: 0 nb: 392 cost: 1.8937656 error rate: 0.731
i: 6 j: 20 nb: 392 cost: 1.9878792 error rate: 0.873
i: 6 j: 40 nb: 392 cost: 1.9282498 error rate: 0.777
i: 6 j: 60 nb: 392 cost: 1.9336413 error rate: 0.746
i: 6 j: 80 nb: 392 cost: 1.8973079 error rate: 0.74
i: 6 j: 100 nb: 392 cost: 1.93706 error rate: 0.76
i: 6 j: 120 nb: 392 cost: 1.9548533 error rate: 0.772
i: 6 j: 140 nb: 392 cost: 1.9298171 error rate: 0.765
i: 6 j: 160 nb: 392 cost: 1.9418708 error rate: 0.754
i: 6 j: 180 nb: 392 cost: 1.959305 error rate: 0.818
i: 6 j: 200 nb: 392 cost: 1.9559997 error rate: 0.76
i: 6 j: 220 nb: 392 cost: 1.9467152 error rate: 0.76
i: 6 j: 240 nb: 392 cost: 1.9565287 error rate: 0.76
i: 6 j: 260 nb: 392 cost: 1.9610537 error rate: 0.76
i: 6 j: 280 nb: 392 cost: 1.9895395 error rate: 0.76
i: 6 j: 300 nb: 392 cost: 1.9968647 error rate: 0.76
i: 6 j: 320 nb: 392 cost: 1.9892621 error rate: 0.76
i: 6 j: 340 nb: 392 cost: 2.0030663 error rate: 0.76
i: 6 j: 360 nb: 392 cost: 2.0031073 error rate: 0.76
i: 6 j: 380 nb: 392 cost: 2.0109031 error rate: 0.76
i: 7 j: 0 nb: 392 cost: 2.013997 error rate: 0.76
i: 7 j: 20 nb: 392 cost: 2.0159564 error rate: 0.76
i: 7 j: 40 nb: 392 cost: 2.0111747 error rate: 0.76
i: 7 j: 60 nb: 392 cost: 1.999576 error rate: 0.76
i: 7 j: 80 nb: 392 cost: 1.9981011 error rate: 0.76
i: 7 j: 100 nb: 392 cost: 2.0011802 error rate: 0.76
i: 7 j: 120 nb: 392 cost: 1.9885037 error rate: 0.76
i: 7 j: 140 nb: 392 cost: 1.9739932 error rate: 0.76
i: 7 j: 160 nb: 392 cost: 1.9740657 error rate: 0.76
i: 7 j: 180 nb: 392 cost: 1.9623386 error rate: 0.76
i: 7 j: 200 nb: 392 cost: 1.960859 error rate: 0.76
i: 7 j: 220 nb: 392 cost: 1.9748791 error rate: 0.76
i: 7 j: 240 nb: 392 cost: 1.94985 error rate: 0.76
i: 7 j: 260 nb: 392 cost: 1.9441016 error rate: 0.76
i: 7 j: 280 nb: 392 cost: 1.9316618 error rate: 0.76
i: 7 j: 300 nb: 392 cost: 1.9465559 error rate: 0.76
i: 7 j: 320 nb: 392 cost: 1.9382385 error rate: 0.76
i: 7 j: 340 nb: 392 cost: 1.9241673 error rate: 0.76
i: 7 j: 360 nb: 392 cost: 1.9278234 error rate: 0.76
i: 7 j: 380 nb: 392 cost: 1.91915 error rate: 0.76
i: 8 j: 0 nb: 392 cost: 1.9312919 error rate: 0.76
i: 8 j: 20 nb: 392 cost: 1.9155451 error rate: 0.76
i: 8 j: 40 nb: 392 cost: 1.927993 error rate: 0.76
i: 8 j: 60 nb: 392 cost: 1.9245306 error rate: 0.76
i: 8 j: 80 nb: 392 cost: 1.9306378 error rate: 0.76
i: 8 j: 100 nb: 392 cost: 1.9206724 error rate: 0.76
i: 8 j: 120 nb: 392 cost: 1.908779 error rate: 0.76
i: 8 j: 140 nb: 392 cost: 1.9209442 error rate: 0.76
i: 8 j: 160 nb: 392 cost: 1.924958 error rate: 0.76
i: 8 j: 180 nb: 392 cost: 1.922931 error rate: 0.76
i: 8 j: 200 nb: 392 cost: 1.926142 error rate: 0.76
i: 8 j: 220 nb: 392 cost: 1.9227632 error rate: 0.76
i: 8 j: 240 nb: 392 cost: 1.9277698 error rate: 0.76
i: 8 j: 260 nb: 392 cost: 1.9076868 error rate: 0.76
i: 8 j: 280 nb: 392 cost: 1.9392792 error rate: 0.76
i: 8 j: 300 nb: 392 cost: 1.9197173 error rate: 0.76
i: 8 j: 320 nb: 392 cost: 1.923045 error rate: 0.76
i: 8 j: 340 nb: 392 cost: 1.917263 error rate: 0.76
i: 8 j: 360 nb: 392 cost: 1.9278615 error rate: 0.76
i: 8 j: 380 nb: 392 cost: 1.9142311 error rate: 0.76
i: 9 j: 0 nb: 392 cost: 1.9176005 error rate: 0.76
i: 9 j: 20 nb: 392 cost: 1.9414244 error rate: 0.86
i: 9 j: 40 nb: 392 cost: 1.9066807 error rate: 0.76
i: 9 j: 60 nb: 392 cost: 1.9116777 error rate: 0.76
i: 9 j: 80 nb: 392 cost: 1.9278219 error rate: 0.76
i: 9 j: 100 nb: 392 cost: 1.911615 error rate: 0.76
i: 9 j: 120 nb: 392 cost: 1.9084913 error rate: 0.76
i: 9 j: 140 nb: 392 cost: 1.9188453 error rate: 0.76
i: 9 j: 160 nb: 392 cost: 1.9286692 error rate: 0.76
i: 9 j: 180 nb: 392 cost: 1.9161183 error rate: 0.76
i: 9 j: 200 nb: 392 cost: 1.9137748 error rate: 0.76
i: 9 j: 220 nb: 392 cost: 1.9265295 error rate: 0.76
i: 9 j: 240 nb: 392 cost: 1.9200742 error rate: 0.76
i: 9 j: 260 nb: 392 cost: 1.9196985 error rate: 0.76
i: 9 j: 280 nb: 392 cost: 1.911799 error rate: 0.76
i: 9 j: 300 nb: 392 cost: 1.9257749 error rate: 0.76
i: 9 j: 320 nb: 392 cost: 1.9153047 error rate: 0.76
i: 9 j: 340 nb: 392 cost: 1.9170078 error rate: 0.76
i: 9 j: 360 nb: 392 cost: 1.9123572 error rate: 0.76
i: 9 j: 380 nb: 392 cost: 1.9091643 error rate: 0.76
<matplotlib.figure.Figure at 0x121022cf8>
In [ ]:
 

© 2018 Nathaniel Dake