Example #1
0
class CNN:
    file_names = None

    def __init__(self):
        self.optimizer = optimizers.Adam()
        self.model_name = "cnn_nantyara"
        if os.path.exists(self.model_name):
            self.load_model()
        else:
            self.crete_model()
        self.optimizer.setup(self.model.collect_parameters())

    def crete_model(self):
        self.model = FunctionSet(
            conv1=F.Convolution2D(3, 32, 3),
            bn1=F.BatchNormalization(32),
            conv2=F.Convolution2D(32, 64, 3, pad=1),
            bn2=F.BatchNormalization(64),
            conv3=F.Convolution2D(64, 64, 3, pad=1),
            fl4=F.Linear(1024, 256),
            fl5=F.Linear(256, 2),
        )

    def get_data(self, ifpath, image_categories, reshape_size=(3, 32, 32)):
        x = []
        x_apd = x.append
        y = []
        y_apd = y.append

        for i_category, category in enumerate(image_categories):
            for i_num in xrange(1, self.get_num_of_images(ifpath, category)):
                image = np.array(Image.open(ifpath + "/" + category + str(i_num) + ".jpeg"), dtype=np.float32).reshape(
                    reshape_size
                )
                x_apd(image)
                y_apd(i_category)

        self.N = len(x)
        return x, np.array(y, dtype=np.int32)

    def get_data_for_predict(self, ifpath, image_name, reshape_size=(3, 32, 32)):
        image = np.array(Image.open(ifpath + "/" + image_name), dtype=np.float32)
        image = cv2.resize(image, (reshape_size[1], reshape_size[2]))
        # print image.shape
        image = image.reshape(reshape_size)
        return [image]

    def forward(self, x_data, y_data, train=True):
        x, t = Variable(np.array(x_data)), Variable(y_data)
        h1 = F.max_pooling_2d(F.relu(self.model.bn1(self.model.conv1(x))), 2)
        h2 = F.max_pooling_2d(F.relu(self.model.bn2(self.model.conv2(h1))), 2)
        h3 = F.max_pooling_2d(F.relu(self.model.conv3(h2)), 2)
        h4 = F.dropout(F.relu(self.model.fl4(h3)), train=train)
        y = self.model.fl5(h4)

        if train:
            return F.softmax_cross_entropy(y, t), F.accuracy(y, t)
        else:
            res = [d for data in F.softmax(y).data for d in data]
            # print res
            return np.array(res).argmax() if len([r for r in res if r > 0.5]) > 0 else "unknown"

    def get_num_of_images(self, path, image_name):
        cmd = "ls images|grep %s|wc -l" % (image_name)
        return int(subprocess.check_output(cmd, shell=True))

    def dump_model(self):
        self.model.to_cpu()
        with open(self.model_name, "wb") as f:
            pickle.dump(self.model, f, -1)

    def load_model(self):
        with open(self.model_name, "rb") as f:
            self.model = pickle.load(f)

    def fit(self, x_train, y_train, epoch=20, batchsize=100):
        for epoch in xrange(1, epoch + 1):
            print "epoch", epoch
            # training
            sum_accuracy = 0
            sum_loss = 0
            for i in xrange(0, self.N, batchsize):
                self.optimizer.zero_grads()
                loss, acc = self.forward(x_train[i : i + batchsize], y_train[i : i + batchsize])
                loss.backward()
                self.optimizer.update()
            print "train mean loss=%s, accuracy =%s" % (str(loss.data), str(acc.data))
        self.dump_model()

    def predict(self, x):
        y = self.forward(x, np.zeros(1, dtype=np.int32), train=False)
        sys.stdout.write(str(self.file_names[y]) if y != "unknonw" else "unknonw")