run_classifier.py 11.3 KB
Newer Older
Y
Yibing Liu 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
"""
Sentiment Classification Task
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import time
import argparse
import numpy as np
import multiprocessing
import sys
sys.path.append("../models/classification/")
L
LiuHao 已提交
16
sys.path.append("../")
Y
Yibing Liu 已提交
17 18 19 20 21 22

from nets import bow_net
from nets import lstm_net
from nets import cnn_net
from nets import bilstm_net
from nets import gru_net
L
LiuHao 已提交
23
from models.model_check import check_cuda
L
LiuHao 已提交
24
from models.model_check import check_version
25
from config import PDConfig
Y
Yibing Liu 已提交
26 27 28 29 30 31 32 33 34 35

import paddle
import paddle.fluid as fluid

import reader
from utils import init_checkpoint

def create_model(args,
                 pyreader_name,
                 num_labels,
36
                 is_prediction=False):
Y
Yibing Liu 已提交
37 38 39 40

    """
    Create Model for sentiment classification
    """
41 42
    
    data = fluid.layers.data(
L
LiuHao 已提交
43
            name="src_ids", shape=[-1, args.max_seq_len], dtype='int64')
44 45 46
    label = fluid.layers.data(
            name="label", shape=[-1, 1], dtype="int64")
    seq_len = fluid.layers.data(
L
LiuHao 已提交
47
            name="seq_len", shape=[-1], dtype="int64")
48 49 50 51 52
    
    data_reader = fluid.io.PyReader(feed_list=[data, label, seq_len], 
        capacity=4, iterable=False)

    if args.model_type == "bilstm_net":
Y
Yibing Liu 已提交
53
        network = bilstm_net
54
    elif args.model_type == "bow_net":
Y
Yibing Liu 已提交
55
        network = bow_net
56
    elif args.model_type == "cnn_net":
Y
Yibing Liu 已提交
57
        network = cnn_net
58
    elif args.model_type == "lstm_net":
Y
Yibing Liu 已提交
59
        network = lstm_net
60
    elif args.model_type == "gru_net":
Y
Yibing Liu 已提交
61 62 63 64
        network = gru_net
    else:
        raise ValueError("Unknown network type!")

65 66
    if is_prediction:
        probs = network(data, seq_len, None, args.vocab_size, is_prediction=is_prediction)
Y
Yibing Liu 已提交
67
        print("create inference model...")
68
        return data_reader, probs, [data.name, seq_len.name]
Y
Yibing Liu 已提交
69

70
    ce_loss, probs = network(data, seq_len, label, args.vocab_size, is_prediction=is_prediction)
Y
Yibing Liu 已提交
71 72 73
    loss = fluid.layers.mean(x=ce_loss)
    num_seqs = fluid.layers.create_tensor(dtype='int64')
    accuracy = fluid.layers.accuracy(input=probs, label=label, total=num_seqs)
74
    return data_reader, loss, accuracy, num_seqs
Y
Yibing Liu 已提交
75 76 77 78 79 80 81 82 83 84 85



def evaluate(exe, test_program, test_pyreader, fetch_list, eval_phase):
    """
    Evaluation Function
    """
    test_pyreader.start()
    total_cost, total_acc, total_num_seqs = [], [], []
    time_begin = time.time()
    while True:
86
        #print("===============")
Y
Yibing Liu 已提交
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
        try:
            np_loss, np_acc, np_num_seqs = exe.run(program=test_program,
                                                   fetch_list=fetch_list,
                                                   return_numpy=False)
            np_loss = np.array(np_loss)
            np_acc = np.array(np_acc)
            np_num_seqs = np.array(np_num_seqs)
            total_cost.extend(np_loss * np_num_seqs)
            total_acc.extend(np_acc * np_num_seqs)
            total_num_seqs.extend(np_num_seqs)
        except fluid.core.EOFException:
            test_pyreader.reset()
            break
    time_end = time.time()
    print("[%s evaluation] ave loss: %f, ave acc: %f, elapsed time: %f s" %
        (eval_phase, np.sum(total_cost) / np.sum(total_num_seqs),
        np.sum(total_acc) / np.sum(total_num_seqs), time_end - time_begin))


def inference(exe, test_program, test_pyreader, fetch_list, infer_phrase):
    """
    Inference Function
    """
    test_pyreader.start()
    time_begin = time.time()
    while True:
        try:
            np_props = exe.run(program=test_program, fetch_list=fetch_list,
                                return_numpy=True)
            for probs in np_props[0]:
                print("%d\t%f\t%f" % (np.argmax(probs), probs[0], probs[1]))
        except fluid.core.EOFException:
            test_pyreader.reset()
            break
    time_end = time.time()
    print("[%s] elapsed time: %f s" % (infer_phrase, time_end - time_begin))


def main(args):
    """
    Main Function
    """
    if args.use_cuda:
        place = fluid.CUDAPlace(int(os.getenv('FLAGS_selected_gpus', '0')))
        dev_count = fluid.core.get_cuda_device_count()
    else:
        place = fluid.CPUPlace()
        dev_count = 1
    exe = fluid.Executor(place)

    task_name = args.task_name.lower()
    processor = reader.SentaProcessor(data_dir=args.data_dir,
                                      vocab_path=args.vocab_path,
140 141
                                      random_seed=args.random_seed,
                                      max_seq_len=args.max_seq_len)
Y
Yibing Liu 已提交
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
    num_labels = len(processor.get_labels())

    if not (args.do_train or args.do_val or args.do_infer):
        raise ValueError("For args `do_train`, `do_val` and `do_infer`, at "
                         "least one of them must be True.")

    startup_prog = fluid.Program()
    if args.random_seed is not None:
        startup_prog.random_seed = args.random_seed

    if args.do_train:
        train_data_generator = processor.data_generator(
            batch_size=args.batch_size,
            phase='train',
            epoch=args.epoch,
            shuffle=True)

        num_train_examples = processor.get_num_examples(phase="train")

        max_train_steps = args.epoch * num_train_examples // args.batch_size // dev_count

        print("Device count: %d" % dev_count)
        print("Num train examples: %d" % num_train_examples)
        print("Max train steps: %d" % max_train_steps)

        train_program = fluid.Program()
Z
zhengya01 已提交
168 169
        if args.enable_ce and args.random_seed is not None:
            train_program.random_seed = args.random_seed
Y
Yibing Liu 已提交
170 171 172

        with fluid.program_guard(train_program, startup_prog):
            with fluid.unique_name.guard():
173
                train_reader, loss, accuracy, num_seqs = create_model(
Y
Yibing Liu 已提交
174 175 176
                    args,
                    pyreader_name='train_reader',
                    num_labels=num_labels,
177
                    is_prediction=False)
Y
Yibing Liu 已提交
178 179 180 181 182 183 184 185 186 187 188

                sgd_optimizer = fluid.optimizer.Adagrad(learning_rate=args.lr)
                sgd_optimizer.minimize(loss)

        if args.verbose:
            lower_mem, upper_mem, unit = fluid.contrib.memory_usage(
                program=train_program, batch_size=args.batch_size)
            print("Theoretical memory usage in training: %.3f - %.3f %s" %
                (lower_mem, upper_mem, unit))

    if args.do_val:
189 190 191 192 193
        test_data_generator = processor.data_generator(
            batch_size=args.batch_size,
            phase='dev',
            epoch=1,
            shuffle=False)
Y
Yibing Liu 已提交
194 195 196
        test_prog = fluid.Program()
        with fluid.program_guard(test_prog, startup_prog):
            with fluid.unique_name.guard():
197
                test_reader, loss, accuracy, num_seqs = create_model(
Y
Yibing Liu 已提交
198 199 200
                    args,
                    pyreader_name='test_reader',
                    num_labels=num_labels,
201
                    is_prediction=False)
Y
Yibing Liu 已提交
202 203 204 205

        test_prog = test_prog.clone(for_test=True)

    if args.do_infer:
206 207 208 209 210
        infer_data_generator = processor.data_generator(
            batch_size=args.batch_size,
            phase='infer',
            epoch=1,
            shuffle=False)
Y
Yibing Liu 已提交
211 212 213
        infer_prog = fluid.Program()
        with fluid.program_guard(infer_prog, startup_prog):
            with fluid.unique_name.guard():
214
                infer_reader, prop, _ = create_model(
Y
Yibing Liu 已提交
215 216 217
                    args,
                    pyreader_name='infer_reader',
                    num_labels=num_labels,
218
                    is_prediction=True)
Y
Yibing Liu 已提交
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
        infer_prog = infer_prog.clone(for_test=True)

    exe.run(startup_prog)

    if args.do_train:
        if args.init_checkpoint:
            init_checkpoint(
                exe,
                args.init_checkpoint,
                main_program=startup_prog)

    elif args.do_val or args.do_infer:
        if not args.init_checkpoint:
            raise ValueError("args 'init_checkpoint' should be set if"
                             "only doing validation or testing!")
        init_checkpoint(
            exe,
            args.init_checkpoint,
            main_program=startup_prog)

    if args.do_train:
        train_exe = exe
241
        train_reader.decorate_sample_list_generator(train_data_generator)
Y
Yibing Liu 已提交
242 243
    else:
        train_exe = None
244 245 246 247
    if args.do_val:
        test_exe = exe
        test_reader.decorate_sample_list_generator(test_data_generator)
    if args.do_infer:
Y
Yibing Liu 已提交
248
        test_exe = exe
249
        infer_reader.decorate_sample_list_generator(infer_data_generator)
Y
Yibing Liu 已提交
250 251

    if args.do_train:
252
        train_reader.start()
Y
Yibing Liu 已提交
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
        steps = 0
        total_cost, total_acc, total_num_seqs = [], [], []
        time_begin = time.time()
        while True:
            try:
                steps += 1
                #print("steps...")
                if steps % args.skip_steps == 0:
                    fetch_list = [loss.name, accuracy.name, num_seqs.name]
                else:
                    fetch_list = []

                outputs = train_exe.run(program=train_program, fetch_list=fetch_list, return_numpy=False)
                #print("finished one step")
                if steps % args.skip_steps == 0:
                    np_loss, np_acc, np_num_seqs = outputs
                    np_loss = np.array(np_loss)
                    np_acc = np.array(np_acc)
                    np_num_seqs = np.array(np_num_seqs)
                    total_cost.extend(np_loss * np_num_seqs)
                    total_acc.extend(np_acc * np_num_seqs)
                    total_num_seqs.extend(np_num_seqs)

                    if args.verbose:
                        verbose = "train pyreader queue size: %d, " % train_pyreader.queue.size()
                        print(verbose)

                    time_end = time.time()
                    used_time = time_end - time_begin
                    print("step: %d, ave loss: %f, "
                        "ave acc: %f, speed: %f steps/s" %
                        (steps, np.sum(total_cost) / np.sum(total_num_seqs),
                        np.sum(total_acc) / np.sum(total_num_seqs),
                        args.skip_steps / used_time))
                    total_cost, total_acc, total_num_seqs = [], [], []
                    time_begin = time.time()

                if steps % args.save_steps == 0:
                    save_path = os.path.join(args.checkpoints,
                                         "step_" + str(steps))
                    fluid.io.save_persistables(exe, save_path, train_program)

                if steps % args.validation_steps == 0:
                    # evaluate dev set
                    if args.do_val:
                        print("do evalatation")
299
                        evaluate(exe, test_prog, test_reader,
Y
Yibing Liu 已提交
300 301 302 303 304 305
                                [loss.name, accuracy.name, num_seqs.name],
                                "dev")

            except fluid.core.EOFException:
                save_path = os.path.join(args.checkpoints, "step_" + str(steps))
                fluid.io.save_persistables(exe, save_path, train_program)
306
                train_reader.reset()
Y
Yibing Liu 已提交
307 308 309 310 311
                break

    # final eval on dev set
    if args.do_val:
        print("Final validation result:")
312
        evaluate(exe, test_prog, test_reader,
Y
Yibing Liu 已提交
313 314 315 316 317
            [loss.name, accuracy.name, num_seqs.name], "dev")

    # final eval on test set
    if args.do_infer:
        print("Final test result:")
318
        inference(exe, infer_prog, infer_reader,
Y
Yibing Liu 已提交
319 320
            [prop.name], "infer")

Z
zhengya01 已提交
321

Y
Yibing Liu 已提交
322
if __name__ == "__main__":
323 324 325
    args = PDConfig('senta_config.json')
    args.build()
    args.print_arguments()
L
LiuHao 已提交
326
    check_cuda(args.use_cuda)
Y
Yibing Liu 已提交
327
    main(args)