The more batch size, the better.



batch size time train mean loss SSE score
64 10855.791047 0.302706 130.547356431 0
128 10692.346976 0.355007 126.1506579977 0
256 11432.415434 0.719253 125.145132211 3878.5556403073
512 11727.674402 0.901692 122.4872463326 25034.6092029519
1024 9788.413161 1.126872 120.8812013435 37818.2934424894

#coding: utf-8
import numpy as np
import sys
import chainer
from chainer import cuda
import chainer.functions as F
from chainer import optimizers
import time
import cPickle

#epoch: 20, time: 10692.346976, train mean loss: 0.355007
#SSE = 126.15065799772859
#SSE Base = 125.63240448203754
#SSE on [angry] = 10.759377271761652
#SSE on [anxious] = 9.174422347429728
#SSE on [confident] = 13.666987468290872
#SSE on [happy] = 49.13119229673229
#SSE on [neutral] = 31.023431109263406
#SSE on [sad] = 6.87797579854229
#SSE on [surprised] = 5.517271705708345
#Score  = 0.0


class FacialEmotions:
    def __init__(self):
        self.startTime = time.clock();

        
#        self.useMax = True
        self.useMax = False


#        self.useModel = True
        self.useModel = False

#        self.train_size10 = True
        self.train_size10 = False

        self.train = []
        self.train_result = []
        self.train_index = 0
        self.test = []
        self.test_index = 0


        self.batchsize = 128
        self.useSmallImage = True
#        self.useSmallImage = False
        self.size = 64
        self.model = chainer.FunctionSet(conv1=F.Convolution2D(3, 32, 3, pad=1),
#                                         l1=F.Linear(32*(self.size/2)*(self.size/2), 256),
                                         conv2=F.Convolution2D(32, 64, 3, pad=1),
                                         l1=F.Linear(64*(self.size/4)*(self.size/4), 256),
#                                         conv3=F.Convolution2D(64, 128, 3, pad=1),
#                                         l1=F.Linear(128*(self.size/8)*(self.size/8), 256),
#                                         conv4=F.Convolution2D(128, 256, 3, pad=1),
#                                         l1=F.Linear(256*(self.size/16)*(self.size/16), 256),
#                                         conv5=F.Convolution2D(256, 512, 3, pad=1),
#                                         l1=F.Linear(512*(self.size/32)*(self.size/32), 256),
                                         l2=F.Linear(256, 7))


        self.folder = "./python/layer2/mini-batch" + str(self.batchsize) + "/"
 
        
    def newImage(self, img):
        size = self.size

        original = np.zeros((3,250,250))
        for r in range(250):
            for c in range(250):
                value = img[r * 250 + c]
                red = (value >> 16) & 255
                green = (value >> 8) & 255
                blue = (value >> 0) & 255
                original[0][r][c] = red
                original[1][r][c] = green
                original[2][r][c] = blue
        
        if self.useSmallImage == True:
            small = np.zeros((3,125,125))
            for color in range(3):
                for r in range(125):
                    for c in range(125):
                        value = original[color][2*r][2*c]
                        value += original[color][2*r][2*c+1]
                        value += original[color][2*r+1][2*c]
                        value += original[color][2*r+1][2*c+1]
                        small[color][r][c] = value/4.0

            res = np.zeros((3,size,size))
            for color in range(3):
                for r in range(size):
                    for c in range(size):
                            res[color][r][c] = small[color][(125/2) - (size/2) + r][(125/2) - (size/2) + c]
        else:
            res = np.zeros((3,size,size))
            for color in range(3):
                for r in range(size):
                    for c in range(size):
                        res[color][r][c] = original[color][(250/2) - (size/2) + r][(250/2) - (size/2) + c]
        return res


    def newImage0(self, img):
        size = 250
        newImg = np.zeros((3,size,size))
        for r in range(size):
            for c in range(size):
                value = img[r*250+c]
                red = (value >> 16) & 255
                green = (value >> 8) & 255
                blue = (value >> 0) & 255
                newImg[0][r][c] = red
                newImg[1][r][c] = green
                newImg[2][r][c] = blue
        return newImg
        
    def training(self, img,emot,*args):
        if self.train_index % 100 == 0:
            print >> sys.stderr, self.train_index

        if self.useModel == True:
            return 1
        
        self.train.append(self.newImage(img))
        
        emotion = 0
        for i in range(7):
            emotion += (i+0) * emot[i]
        self.train_result.append(emotion)
        
        
        self.train_index+=1
        
        if self.train_size10 == True and self.train_index == 10:
            return 1
        return 0
        
    def testing(self, img,*args):
        if self.useModel == True and self.test_index == 0:
            pkl_file = open(self.folder + "FacialEmotions.pkl", "rb")
            self.model = cPickle.load(pkl_file)


        elif self.test_index == 0:
            
            self.train = np.array(self.train, dtype=np.float32)
            self.train_result = np.array(self.train_result, dtype=np.int32)
            self.test = np.array(self.test, dtype=np.float32)

            self.train /= 255.0
            self.test /= 255.0
            
            def forward(x_data, y_data, train=True):
                x, t = chainer.Variable(x_data), chainer.Variable(y_data)
                h = F.max_pooling_2d(F.relu(self.model.conv1(x)), 2)
                h = F.max_pooling_2d(F.relu(self.model.conv2(h)), 2)
                h = F.dropout(F.relu(self.model.l1(h)), train=train)
                y = self.model.l2(h)
                if train:
                    return F.softmax_cross_entropy(y, t)
                else:
                    return F.accuracy(y, t)



            optimizer = optimizers.Adam()
            optimizer.setup(self.model)



            batchsize = self.batchsize
            n_epoch = 20
            xp = np
            X_train = self.train
            y_train = self.train_result
            N = len(y_train)
            print >> sys.stderr, "start epoch, time: %f" % (time.clock() - self.startTime)
            for epoch in range(1, n_epoch + 1):

                perm = np.random.permutation(N)
                sum_loss = 0
                for i in range(0, N, batchsize):
                    x_batch = xp.asarray(X_train[perm[i:i + batchsize]])
                    y_batch = xp.asarray(y_train[perm[i:i + batchsize]])

                    optimizer.zero_grads()
                    loss = forward(x_batch, y_batch)
                    loss.backward()
                    optimizer.update()
                    sum_loss += float(loss.data) * len(y_batch)

                print >> sys.stderr, "epoch: %d, time: %f, train mean loss: %f" % (epoch,time.clock() - self.startTime, sum_loss / N)








        if self.useModel == False:
            self.model.to_cpu()
            cPickle.dump(self.model, open(self.folder + "FacialEmotions.pkl", "wb"), -1)

        def forward_predict(x_data, train=True):
            x = chainer.Variable(x_data)
            h = F.max_pooling_2d(F.relu(self.model.conv1(x)), 2)
            h = F.max_pooling_2d(F.relu(self.model.conv2(h)), 2)
            h = F.dropout(F.relu(self.model.l1(h)), train=train)
            y = self.model.l2(h)
            return y
        
        self.test_index+=1

        newImg = self.newImage(img)
        
        test = []
        test.append(newImg)
        test = np.array(test, dtype=np.float32)
        test /= 255.0
        
        predict = forward_predict(test)



        if self.useMax == True:
            res = []
            max_value = max(predict.data[0])
            for value in predict.data[0]:
                if value == max_value:
                    res.append(1)
                else:
                    res.append(0)
            return res
        
        else: 
            min_value = min(predict.data[0])
            res0 = []
            for value in predict.data[0]:
                res0.append(value-min_value)
            sum = 0
            for value in res0:
                sum += value
            res = []
            for value in res0:
                res.append(value/sum)
            return res


    
    
if __name__ == "__main__":
    fe = FacialEmotions()
    N = int(raw_input())
    for i in range(N):
        S = int(raw_input())
        imageData = []
        emotions = []
        for j in range(S):
            imageData.append(int(raw_input()))
        for j in range(7):
            emotions.append(float(raw_input()))
        ret = fe.training(imageData, emotions)
        print ret
        sys.stdout.flush()
        if ret == 1:
    	    break	
    
    M = int(raw_input())
    for i in range(M):
        S = int(raw_input())
        imageData = []
        for j in range(S):
            imageData.append(int(raw_input()))
        ret = fe.testing(imageData)
        for j in ret:
            print j

        sys.stdout.flush()