def CNNTrain(batch_size=50, epochs=100, rate=0.003, filepath='./predict.csv'):
    '''
    We construct a three layers model: input layer, hidden layer and output layer
    :param batch_size:
    :return:
    '''
    testData = pd.read_csv('./testFeature.csv')
    x = tf.placeholder(tf.float32, [None, 15], name="data")
    y_ = tf.placeholder(tf.float32, [None, 2], name='label')
    with tf.name_scope("layer_in"):
        W_in = tf.Variable(tf.truncated_normal([15, 400],stddev=0.1), name="W1")
        b_in = tf.Variable(tf.truncated_normal([400], stddev=0.1), name="b1")
        hidden_in = tf.nn.relu(tf.matmul(x, W_in) + b_in, name="hidden1")
        hidden_in_flat = tf.reshape(hidden_in, [-1, 20, 20, 1], name="hidden1_flat")
    with tf.name_scope("conv_1"):
        W_conv1 = weight_variable([5, 5, 1, 32])
        b_conv1 = bias_variable([32])
        h_conv1 = tf.nn.relu(conv2d(hidden_in_flat, W_conv1) + b_conv1)
        h_pool1 = max_pool_2x2(h_conv1)
    with tf.name_scope("conv_2"):
        W_conv2 = weight_variable([5, 5, 32, 64])
        b_conv2 = bias_variable([64])
        h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
        h_pool2 = max_pool_2x2(h_conv2)
    with tf.name_scope("layer_hidden_1"):
        W1 = weight_variable([5 * 5 * 64, 128])
        b1 = bias_variable([128])
        h_pool2_flat = tf.reshape(h_pool2, [-1, 5 * 5 * 64])
        hidden1 = tf.nn.relu(tf.matmul(h_pool2_flat, W1) + b1)
    with tf.name_scope("layer_hidden_2"):
        W2 = weight_variable([128, 64])
        b2 = bias_variable([64])
        hidden2 = tf.nn.relu(tf.matmul(hidden1, W2) + b2)
    with tf.name_scope("layer_out"):
        W_out = weight_variable([64, 2])
        b_out = bias_variable([2])
        hidden_out = tf.nn.softmax(tf.matmul(hidden2, W_out) + b_out, name="output")
    with tf.name_scope("cost"):
        vars = tf.trainable_variables()
        lossL2 = tf.add_n([tf.nn.l2_loss(v) for v in vars if 'b' not in v.name]) * 0.05
        cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=hidden_out, labels=y_)+lossL2)
        
    with tf.name_scope("train"):
        train_step = tf.train.GradientDescentOptimizer(learning_rate=rate).minimize(cost)
    with tf.name_scope("predict"):
        predict_step = tf.argmax(hidden_out, 1)
    with tf.name_scope("save_params"):
        saver = tf.train.Saver()
    
    init = tf.initialize_all_variables()
    with tf.Session() as sess:
        sess.run(init)
        epoch = 1
        best = 0
        while epoch <= epochs:
            print("epoch: ", epoch)
            train_X, train_Y = shuffle()
            validation_X, validation_Y = getValidation()
            for i in xrange(0, 700, batch_size):
                sess.run(train_step, feed_dict={x: train_X[i:i + batch_size], y_: train_Y[i:i + batch_size]})
                correct_prediction = tf.equal(tf.argmax(hidden_out, 1), tf.argmax(y_, 1))
                accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
                print("mini_batch", i, "~", i + batch_size, "of", epoch, "epochs")
                print("accuracy on train set: {}".format(sess.run(accuracy, feed_dict={x: train_X, y_: train_Y})))
                print("accuracy on validation set: {}, the current best accuracy: {}".format(sess.run(accuracy, feed_dict={x: validation_X, y_: validation_Y}), best))
                
                if best < sess.run(accuracy, feed_dict={x: validation_X, y_: validation_Y}):
                    best = sess.run(accuracy, feed_dict={x: validation_X, y_: validation_Y})
                    
                    savePredict(sess.run(predict_step, feed_dict={x: testData}), filepath=filepath)
            epoch += 1
        print("The best accuracy: ", best)