Skip to content

Commit e858471

Browse files
authored
Add conv model for sentiment analysis with new API (#10847)
1 parent 67f5eaf commit e858471

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from __future__ import print_function
16+
17+
import paddle
18+
import paddle.fluid as fluid
19+
from functools import partial
20+
import numpy as np
21+
22+
CLASS_DIM = 2
23+
EMB_DIM = 128
24+
HID_DIM = 512
25+
BATCH_SIZE = 128
26+
27+
28+
def convolution_net(data, input_dim, class_dim, emb_dim, hid_dim):
29+
emb = fluid.layers.embedding(
30+
input=data, size=[input_dim, emb_dim], is_sparse=True)
31+
conv_3 = fluid.nets.sequence_conv_pool(
32+
input=emb,
33+
num_filters=hid_dim,
34+
filter_size=3,
35+
act="tanh",
36+
pool_type="sqrt")
37+
conv_4 = fluid.nets.sequence_conv_pool(
38+
input=emb,
39+
num_filters=hid_dim,
40+
filter_size=4,
41+
act="tanh",
42+
pool_type="sqrt")
43+
prediction = fluid.layers.fc(input=[conv_3, conv_4],
44+
size=class_dim,
45+
act="softmax")
46+
return prediction
47+
48+
49+
def inference_program(word_dict):
50+
data = fluid.layers.data(
51+
name="words", shape=[1], dtype="int64", lod_level=1)
52+
53+
dict_dim = len(word_dict)
54+
net = convolution_net(data, dict_dim, CLASS_DIM, EMB_DIM, HID_DIM)
55+
return net
56+
57+
58+
def train_program(word_dict):
59+
prediction = inference_program(word_dict)
60+
label = fluid.layers.data(name="label", shape=[1], dtype="int64")
61+
cost = fluid.layers.cross_entropy(input=prediction, label=label)
62+
avg_cost = fluid.layers.mean(cost)
63+
accuracy = fluid.layers.accuracy(input=prediction, label=label)
64+
return [avg_cost, accuracy]
65+
66+
67+
def train(use_cuda, train_program, save_dirname):
68+
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
69+
optimizer = fluid.optimizer.Adagrad(learning_rate=0.002)
70+
71+
word_dict = paddle.dataset.imdb.word_dict()
72+
trainer = fluid.Trainer(
73+
train_func=partial(train_program, word_dict),
74+
place=place,
75+
optimizer=optimizer)
76+
77+
def event_handler(event):
78+
if isinstance(event, fluid.EndEpochEvent):
79+
test_reader = paddle.batch(
80+
paddle.dataset.imdb.test(word_dict), batch_size=BATCH_SIZE)
81+
avg_cost, acc = trainer.test(
82+
reader=test_reader, feed_order=['words', 'label'])
83+
84+
print("avg_cost: %s" % avg_cost)
85+
print("acc : %s" % acc)
86+
87+
if acc > 0.2: # Smaller value to increase CI speed
88+
trainer.save_params(save_dirname)
89+
trainer.stop()
90+
91+
else:
92+
print('BatchID {0}, Test Loss {1:0.2}, Acc {2:0.2}'.format(
93+
event.epoch + 1, avg_cost, acc))
94+
if math.isnan(avg_cost):
95+
sys.exit("got NaN loss, training failed.")
96+
elif isinstance(event, fluid.EndStepEvent):
97+
print("Step {0}, Epoch {1} Metrics {2}".format(
98+
event.step, event.epoch, map(np.array, event.metrics)))
99+
if event.step == 1: # Run 2 iterations to speed CI
100+
trainer.save_params(save_dirname)
101+
trainer.stop()
102+
103+
train_reader = paddle.batch(
104+
paddle.reader.shuffle(
105+
paddle.dataset.imdb.train(word_dict), buf_size=25000),
106+
batch_size=BATCH_SIZE)
107+
108+
trainer.train(
109+
num_epochs=1,
110+
event_handler=event_handler,
111+
reader=train_reader,
112+
feed_order=['words', 'label'])
113+
114+
115+
def infer(use_cuda, inference_program, save_dirname=None):
116+
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
117+
word_dict = paddle.dataset.imdb.word_dict()
118+
119+
inferencer = fluid.Inferencer(
120+
infer_func=partial(inference_program, word_dict),
121+
param_path=save_dirname,
122+
place=place)
123+
124+
def create_random_lodtensor(lod, place, low, high):
125+
data = np.random.random_integers(low, high,
126+
[lod[-1], 1]).astype("int64")
127+
res = fluid.LoDTensor()
128+
res.set(data, place)
129+
res.set_lod([lod])
130+
return res
131+
132+
lod = [0, 4, 10]
133+
tensor_words = create_random_lodtensor(
134+
lod, place, low=0, high=len(word_dict) - 1)
135+
results = inferencer.infer({'words': tensor_words})
136+
print("infer results: ", results)
137+
138+
139+
def main(use_cuda):
140+
if use_cuda and not fluid.core.is_compiled_with_cuda():
141+
return
142+
save_path = "understand_sentiment_conv.inference.model"
143+
train(use_cuda, train_program, save_path)
144+
infer(use_cuda, inference_program, save_path)
145+
146+
147+
if __name__ == '__main__':
148+
for use_cuda in (False, True):
149+
main(use_cuda=use_cuda)

0 commit comments

Comments
 (0)