注意:全部代码为PaddlePaddle1版本的代码

Helloworld

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# helloworld示例
import paddle.fluid as fluid

# 创建两个类型为int64, 形状为1*1张量
x = fluid.layers.fill_constant(shape=[1], dtype="int64", value=5)
y = fluid.layers.fill_constant(shape=[1], dtype="int64", value=1)
z = x + y # z只是一个对象,没有run,所以没有值

# 创建执行器
place = fluid.CPUPlace() # 指定在CPU上执行
exe = fluid.Executor(place) # 创建执行器
result = exe.run(fluid.default_main_program(),
fetch_list=[z]) #返回哪个结果
print(result) # result为多维张量

张量操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import paddle.fluid as fluid
import numpy

# 创建x, y两个2行3列,类型为float32的变量(张量)
x = fluid.layers.data(name="x", shape=[2, 3], dtype="float32")
y = fluid.layers.data(name="y", shape=[2, 3], dtype="float32")

x_add_y = fluid.layers.elementwise_add(x, y) # 两个张量按元素相加
x_mul_y = fluid.layers.elementwise_mul(x, y) # 两个张量按元素相乘

place = fluid.CPUPlace() # 指定在CPU上执行
exe = fluid.Executor(place) # 创建执行器
exe.run(fluid.default_startup_program()) # 初始化网络

a = numpy.array([[1, 2, 3],
[4, 5, 6]]) # 输入x, 并转换为数组
b = numpy.array([[1, 1, 1],
[2, 2, 2]]) # 输入y, 并转换为数组

params = {"x": a, "y": b}
outs = exe.run(fluid.default_main_program(), # 默认程序上执行
feed=params, # 喂入参数
fetch_list=[x_add_y, x_mul_y]) # 获取结果
for i in outs:
print(i)

简单线性回归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# 简单线性回归
import paddle
import paddle.fluid as fluid
import numpy as np
import matplotlib.pyplot as plt

train_data = np.array([[0.5], [0.6], [0.8], [1.1], [1.4]]).astype('float32')
y_true = np.array([[5.0], [5.5], [6.0], [6.8], [6.8]]).astype('float32')

# 定义数据数据类型
x = fluid.layers.data(name="x", shape=[1], dtype="float32")
y = fluid.layers.data(name="y", shape=[1], dtype="float32")
# 通过全连接网络进行预测
y_preict = fluid.layers.fc(input=x, size=1, act=None)
# 添加损失函数
cost = fluid.layers.square_error_cost(input=y_preict, label=y)
avg_cost = fluid.layers.mean(cost) # 求均方差
# 定义优化方法
optimizer = fluid.optimizer.SGD(learning_rate=0.01)
optimizer.minimize(avg_cost) # 指定最小化均方差值

# 搭建网络
place = fluid.CPUPlace() # 指定在CPU执行
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program()) # 初始化系统参数

# 开始训练, 迭代100次
costs = []
iters = []
values = []
params = {"x": train_data, "y": y_true}
for i in range(200):
outs = exe.run(feed=params, fetch_list=[y_preict.name, avg_cost.name])
iters.append(i) # 迭代次数
costs.append(outs[1][0]) # 损失值
print("i:", i, " cost:", outs[1][0])

# 线性模型可视化
tmp = np.random.rand(10, 1) # 生成10行1列的均匀随机数组
tmp = tmp * 2 # 范围放大到0~2之间
tmp.sort(axis=0) # 排序
x_test = np.array(tmp).astype("float32")
params = {"x": x_test, "y": x_test} # y参数不参加计算,只需传一个参数避免报错
y_out = exe.run(feed=params, fetch_list=[y_preict.name]) # 预测
y_test = y_out[0]

# 损失函数可视化
plt.figure("Trainging")
plt.title("Training Cost", fontsize=24)
plt.xlabel("Iter", fontsize=14)
plt.ylabel("Cost", fontsize=14)
plt.plot(iters, costs, color="red", label="Training Cost") # 绘制损失函数曲线
plt.grid() # 绘制网格线
plt.savefig("train.png") # 保存图片

# 线性模型可视化
plt.figure("Inference")
plt.title("Linear Regression", fontsize=24)
plt.plot(x_test, y_test, color="red", label="inference") # 绘制模型线条
plt.scatter(train_data, y_true) # 原始样本散点图

plt.legend()
plt.grid() # 绘制网格线
plt.savefig("infer.png") # 保存图片
plt.show() # 显示图片

波士顿房价预测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
140
141
# 多元回归示例:波士顿房价预测
''' 数据集介绍:
1) 共506行,每行14列,前13列描述房屋特征信息,最后一列为价格中位数
2) 考虑了犯罪率(CRIM) 宅用地占比(ZN)
非商业用地所占尺寸(INDUS) 查尔斯河虚拟变量(CHAS)
环保指数(NOX) 每栋住宅的房间数(RM)
1940年以前建成的自建单位比例(AGE) 距离5个波士顿就业中心的加权距离(DIS)
距离高速公路便利指数(RAD) 每一万元不动产税率(TAX)
教师学生比(PTRATIO) 黑人比例(B)
房东属于中低收入比例(LSTAT)
'''
import paddle
import paddle.fluid as fluid
import numpy as np
import os
import matplotlib.pyplot as plt

# step1: 数据准备
# paddle提供了uci_housing训练集、测试集,直接读取并返回数据
BUF_SIZE = 500
BATCH_SIZE = 20

# 训练数据集读取器
random_reader = paddle.reader.shuffle(paddle.dataset.uci_housing.train(),
buf_size=BUF_SIZE) # 创建随机读取器
train_reader = paddle.batch(random_reader, batch_size=BATCH_SIZE) # 训练数据读取器

# 打印数据
#train_data = paddle.dataset.uci_housing.train()
#for sample_data in train_data():
# print(sample_data)

# step2: 配置网络
# 定义输入、输出,类型均为张量
x = fluid.layers.data(name="x", shape=[13], dtype="float32")
y = fluid.layers.data(name="y", shape=[1], dtype="float32")
# 定义个简单的线性网络,连接输出层、输出层
y_predict = fluid.layers.fc(input=x, # 输入数据
size=1, # 输出值个数
act=None) # 激活函数
# 定义损失函数,并将损失函数指定给优化器
cost = fluid.layers.square_error_cost(input=y_predict, # 预测值,张量
label=y) # 期望值,张量
avg_cost = fluid.layers.mean(cost) # 求损失值平均数
optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.001) # 使用随机梯度下降优化器
opts = optimizer.minimize(avg_cost) # 优化器最小化损失值

# 创建新的program用于测试计算
#test_program = fluid.default_main_program().clone(for_test=True)

# step3: 模型训练、模型评估
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())

feeder = fluid.DataFeeder(place=place, feed_list=[x, y])

iter = 0
iters = []
train_costs = []

EPOCH_NUM = 120
model_save_dir = "./model/uci_housing" # 模型保存路径
for pass_id in range(EPOCH_NUM):
train_cost = 0
i = 0
for data in train_reader():
i += 1
train_cost = exe.run(program=fluid.default_main_program(),
feed=feeder.feed(data),
fetch_list=[avg_cost])
if i % 20 == 0: # 每20笔打印一次损失函数值
print("PassID: %d, Cost: %0.5f" % (pass_id, train_cost[0][0]))
iter = iter + BATCH_SIZE # 加上每批次笔数
iters.append(iter) # 记录笔数
train_costs.append(train_cost[0][0]) # 记录损失值

# 保存模型
if not os.path.exists(model_save_dir): # 如果存储模型的目录不存在,则创建
os.makedirs(model_save_dir)
fluid.io.save_inference_model(model_save_dir, # 保存模型的路径
["x"], # 预测需要喂入的数据
[y_predict], # 保存预测结果的变量
exe) # 模型
# 训练过程可视化
plt.figure("Training Cost")
plt.title("Training Cost", fontsize=24)
plt.xlabel("iter", fontsize=14)
plt.ylabel("cost", fontsize=14)
plt.plot(iters, train_costs, color="red", label="Training Cost")
plt.grid()
plt.savefig("train.png")

# step4: 模型预测
infer_exe = fluid.Executor(place) # 创建用于预测的Executor
infer_scope = fluid.core.Scope() # 修改全局/默认作用域, 运行时中的所有变量都将分配给新的scope
infer_result = [] #预测值列表
ground_truths = [] #真实值列表

# with fluid.scope_guard(infer_scope):
# 加载模型,返回三个值
# program: 预测程序(包含了数据、计算规则)
# feed_target_names: 需要喂入的变量
# fetch_targets: 预测结果保存的变量
[infer_program, feed_target_names, fetch_targets] = \
fluid.io.load_inference_model(model_save_dir, # 模型保存路径
infer_exe) # 要执行模型的Executor
# 获取测试数据
infer_reader = paddle.batch(paddle.dataset.uci_housing.test(),
batch_size=200) # 测试数据读取器
test_data = next(infer_reader()) # 获取一条数据
test_x = np.array([data[0] for data in test_data]).astype("float32")
test_y = np.array([data[1] for data in test_data]).astype("float32")

x_name = feed_target_names[0] # 模型中保存的输入参数名称
results = infer_exe.run(infer_program, # 预测program
feed={x_name: np.array(test_x)}, # 喂入预测的值
fetch_list=fetch_targets) # 预测结果
# 预测值
for idx, val in enumerate(results[0]):
print("%d: %.2f" % (idx, val))
infer_result.append(val)

# 真实值
for idx, val in enumerate(test_y):
print("%d: %.2f" % (idx, val))
ground_truths.append(val)

# 可视化
plt.figure('scatter')
plt.title("TestFigure", fontsize=24)
plt.xlabel("ground truth", fontsize=14)
plt.ylabel("infer result", fontsize=14)
x = np.arange(1, 30)
y = x
plt.plot(x, y)
plt.scatter(ground_truths, infer_result, color="green", label="Test")
plt.grid()
plt.legend()
plt.savefig("predict.png")
plt.show()

增量模型训练

1)模型训练与保存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# 线性回归增量训练、模型保存、固化
import paddle
import paddle.fluid as fluid
import numpy as np
import matplotlib.pyplot as plt
import os

train_data = np.array([[0.5], [0.6], [0.8], [1.1], [1.4]]).astype('float32')
y_true = np.array([[5.0], [5.5], [6.0], [6.8], [6.8]]).astype('float32')

# 定义数据数据类型
x = fluid.layers.data(name="x", shape=[1], dtype="float32")
y = fluid.layers.data(name="y", shape=[1], dtype="float32")
# 通过全连接网络进行预测
y_predict = fluid.layers.fc(input=x, size=1, act=None)
# 添加损失函数
cost = fluid.layers.square_error_cost(input=y_predict, label=y)
avg_cost = fluid.layers.mean(cost) # 求均方差
# 定义优化方法
optimizer = fluid.optimizer.SGD(learning_rate=0.01)
optimizer.minimize(avg_cost) # 指定最小化均方差值

# 搭建网络
place = fluid.CPUPlace() # 指定在CPU执行
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program()) # 初始化系统参数

model_save_dir = "./model/lr_persis/"
if os.path.exists(model_save_dir):
fluid.io.load_persistables(exe, model_save_dir, fluid.default_main_program())
print("加载增量模型成功.")

# 开始迭代训练
costs = []
iters = []
values = []
params = {"x": train_data, "y": y_true}
for i in range(50):
outs = exe.run(feed=params, fetch_list=[y_predict.name, avg_cost.name])
iters.append(i) # 迭代次数
costs.append(outs[1][0]) # 损失值
print("%d: %f" % (i, outs[1][0]))

# 损失函数可视化
plt.figure("Trainging")
plt.title("Training Cost", fontsize=24)
plt.xlabel("Iter", fontsize=14)
plt.ylabel("Cost", fontsize=14)
plt.plot(iters, costs, color="red", label="Training Cost") # 绘制损失函数曲线
plt.grid() # 绘制网格线
plt.savefig("train.png") # 保存图片


plt.legend()
plt.grid() # 绘制网格线
plt.savefig("infer.png") # 保存图片
# plt.show() # 显示图片
print("训练完成.")

# 保存增量模型
if not os.path.exists(model_save_dir): # 如果存储模型的目录不存在,则创建
os.makedirs(model_save_dir)
fluid.io.save_persistables(exe, model_save_dir, fluid.default_main_program())

print("保存增量模型成功.")

# 保存最终模型
freeze_dir = "./model/lr_freeze/"
if not os.path.exists(freeze_dir): # 如果存储模型的目录不存在,则创建
os.makedirs(freeze_dir)
fluid.io.save_inference_model(freeze_dir, # 保存模型的路径
["x"], # 预测需要喂入的数据
[y_predict], # 保存预测结果的变量
exe) # 模型

print("模型保存成功.")

2)模型加载与使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 增量模型加载
import paddle
import paddle.fluid as fluid
import numpy as np
import math
import os
import matplotlib.pyplot as plt

train_data = np.array([[0.5], [0.6], [0.8], [1.1], [1.4]]).astype('float32')
y_true = np.array([[5.0], [5.5], [6.0], [6.8], [6.8]]).astype('float32')

# 模型预测
infer_exe = fluid.Executor(fluid.CPUPlace()) # 创建用于预测的Executor
infer_result = [] #预测值列表

freeze_dir = "./model/lr_freeze/"
[infer_program, feed_target_names, fetch_targets] = \
fluid.io.load_inference_model(freeze_dir, # 模型保存路径
infer_exe) # 要执行模型的Executor


tmp = np.random.rand(10, 1) # 生成10行1列的均匀随机数组
tmp = tmp * 2 # 范围放大到0~2之间
tmp.sort(axis=0) # 排序
x_test = np.array(tmp).astype("float32")
x_name = feed_target_names[0] # 模型中保存的输入参数名称

# 执行预测
y_out = infer_exe.run(infer_program, # 预测program
feed={x_name: x_test}, # 喂入预测的值
fetch_list=fetch_targets) # 预测结果
y_test = y_out[0]


# 线性模型可视化
plt.figure("Inference")
plt.title("Linear Regression", fontsize=24)
plt.plot(x_test, y_test, color="red", label="inference") # 绘制模型线条
plt.scatter(train_data, y_true) # 原始样本散点图

plt.legend()
plt.grid() # 绘制网格线
plt.savefig("infer.png") # 保存图片
plt.show() # 显示图片

三次增量训练效果:

增量训练效果

水果识别

  1. 数据预处理部分:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# 02_fruits.py
# 利用深层CNN实现水果分类
# 数据集:爬虫从百度图片搜索结果爬取
# 内容:包含1036张水果图片,共5个类别(苹果288张、香蕉275张、葡萄216张、橙子276张、梨251张)

############################ 预处理部分 ################################
import os

name_dict = {"apple":0, "banana":1, "grape":2, "orange":3, "pear":4}
data_root_path = "data/fruits/" # 数据样本所在目录
test_file_path = data_root_path + "test.txt" #测试文件路径
train_file_path = data_root_path + "train.txt" # 训练文件路径
name_data_list = {} # 记录每个类别有哪些图片 key:水果名称 value:图片路径构成的列表

# 将图片路径存入name_data_list字典中
def save_train_test_file(path, name):
if name not in name_data_list: # 该类别水果不在字典中,则新建一个列表插入字典
img_list = []
img_list.append(path) # 将图片路径存入列表
name_data_list[name] = img_list # 将图片列表插入字典
else: # 该类别水果在字典中,直接添加到列表
name_data_list[name].append(path)

# 遍历数据集下面每个子目录,将图片路径写入上面的字典
dirs = os.listdir(data_root_path) # 列出数据集目下所有的文件和子目录
for d in dirs:
full_path = data_root_path + d # 拼完整路径

if os.path.isdir(full_path): # 是一个子目录
imgs = os.listdir(full_path) # 列出子目录中所有的文件
for img in imgs:
save_train_test_file(full_path + "/" + img, #拼图片完整路径
d) # 以子目录名称作为类别名称
else: # 文件
pass

# 将name_data_list字典中的内容写入文件
## 清空训练集和测试集文件
with open(test_file_path, "w") as f:
pass

with open(train_file_path, "w") as f:
pass

# 遍历字典,将字典中的内容写入训练集和测试集
for name, img_list in name_data_list.items():
i = 0
num = len(img_list) # 获取每个类别图片数量
print("%s: %d张" % (name, num))
# 写训练集和测试集
for img in img_list:
if i % 10 == 0: # 每10笔写一笔测试集
with open(test_file_path, "a") as f: #以追加模式打开测试集文件
line = "%s\t%d\n" % (img, name_dict[name]) # 拼一行
f.write(line) # 写入文件
else: # 训练集
with open(train_file_path, "a") as f: #以追加模式打开测试集文件
line = "%s\t%d\n" % (img, name_dict[name]) # 拼一行
f.write(line) # 写入文件

i += 1 # 计数器加1

print("数据预处理完成.")
  1. 模型训练与评估
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
140
141
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
import paddle
import paddle.fluid as fluid
import numpy
import sys
import os
from multiprocessing import cpu_count
import time
import matplotlib.pyplot as plt

def train_mapper(sample):
"""
根据传入的样本数据(一行文本)读取图片数据并返回
:param sample: 元组,格式为(图片路径,类别)
:return:返回图像数据、类别
"""
img, label = sample # img为路径,label为类别
if not os.path.exists(img):
print(img, "图片不存在")

# 读取图片内容
img = paddle.dataset.image.load_image(img)
# 对图片数据进行简单变换,设置成固定大小
img = paddle.dataset.image.simple_transform(im=img, # 原始图像数据
resize_size=128, # 图像要设置的大小
crop_size=128, # 裁剪图像大小
is_color=True, # 彩色图像
is_train=True) # 随机裁剪
# 归一化处理,将每个像素值转换到0~1
img = img.astype("float32") / 255.0
return img, label # 返回图像、类别

# 从训练集中读取数据
def train_r(train_list, buffered_size=1024):
def reader():
with open(train_list, "r") as f:
lines = [line.strip() for line in f] # 读取所有行,并去空格
for line in lines:
# 去掉一行数据的换行符,并按tab键拆分,存入两个变量
img_path, lab = line.replace("\n","").split("\t")
yield img_path, int(lab) # 返回图片路径、类别(整数)
return paddle.reader.xmap_readers(train_mapper, # 将reader读取的数进一步处理
reader, # reader读取到的数据传递给train_mapper
cpu_count(), # 线程数量
buffered_size) # 缓冲区大小

# 搭建CNN函数
# 结构:输入层 --> 卷积/激活/池化/dropout --> 卷积/激活/池化/dropout -->
# 卷积/激活/池化/dropout --> fc --> dropout --> fc(softmax)
def convolution_neural_network(image, type_size):
"""
创建CNN
:param image: 图像数据
:param type_size: 输出类别数量
:return: 分类概率
"""
# 第一组 卷积/激活/池化/dropout
conv_pool_1 = fluid.nets.simple_img_conv_pool(input=image, # 原始图像数据
filter_size=3, # 卷积核大小
num_filters=32, # 卷积核数量
pool_size=2, # 2*2区域池化
pool_stride=2, # 池化步长值
act="relu")#激活函数
drop = fluid.layers.dropout(x=conv_pool_1, dropout_prob=0.5)

# 第二组
conv_pool_2 = fluid.nets.simple_img_conv_pool(input=drop, # 以上一个drop输出作为输入
filter_size=3, # 卷积核大小
num_filters=64, # 卷积核数量
pool_size=2, # 2*2区域池化
pool_stride=2, # 池化步长值
act="relu")#激活函数
drop = fluid.layers.dropout(x=conv_pool_2, dropout_prob=0.5)

# 第三组
conv_pool_3 = fluid.nets.simple_img_conv_pool(input=drop, # 以上一个drop输出作为输入
filter_size=3, # 卷积核大小
num_filters=64, # 卷积核数量
pool_size=2, # 2*2区域池化
pool_stride=2, # 池化步长值
act="relu")#激活函数
drop = fluid.layers.dropout(x=conv_pool_3, dropout_prob=0.5)

# 全连接层
fc = fluid.layers.fc(input=drop, size=512, act="relu")
# dropout
drop = fluid.layers.dropout(x=fc, dropout_prob=0.5)
# 输出层(fc)
predict = fluid.layers.fc(input=drop, # 输入
size=type_size, # 输出值的个数(5个类别)
act="softmax") # 输出层采用softmax作为激活函数
return predict


# 定义reader
BATCH_SIZE = 32 # 批次大小
trainer_reader = train_r(train_list=train_file_path) #原始reader
random_train_reader = paddle.reader.shuffle(reader=trainer_reader,
buf_size=1300) # 包装成随机读取器
batch_train_reader = paddle.batch(random_train_reader,
batch_size=BATCH_SIZE) # 批量读取器
# 变量
image = fluid.layers.data(name="image", shape=[3, 128, 128], dtype="float32")
label = fluid.layers.data(name="label", shape=[1], dtype="int64")

# 调用函数,创建CNN
predict = convolution_neural_network(image=image, type_size=5)
# 损失函数:交叉熵
cost = fluid.layers.cross_entropy(input=predict, # 预测结果
label=label) # 真实结果
avg_cost = fluid.layers.mean(cost)
# 计算准确率
accuracy = fluid.layers.accuracy(input=predict, # 预测结果
label=label) # 真实结果
# 优化器
optimizer = fluid.optimizer.Adam(learning_rate=0.001)
optimizer.minimize(avg_cost) # 将损失函数值优化到最小

# 执行器
# place = fluid.CPUPlace()
place = fluid.CUDAPlace(0) # GPU训练
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
# feeder
feeder = fluid.DataFeeder(feed_list=[image, label], # 指定要喂入数据
place=place)

model_save_dir = "model/fruits/" # 模型保存路径
costs = [] # 记录损失值
accs = [] # 记录准确度
times = 0
batches = [] # 迭代次数

# 开始训练
for pass_id in range(40):
train_cost = 0 # 临时变量,记录每次训练的损失值
for batch_id, data in enumerate(batch_train_reader()): # 循环读取样本,执行训练
times += 1
train_cost, train_acc = exe.run(program=fluid.default_main_program(),
feed=feeder.feed(data), # 喂入参数
fetch_list=[avg_cost, accuracy])# 获取损失值、准确率
if batch_id % 20 == 0:
print("pass_id:%d, step:%d, cost:%f, acc:%f" %
(pass_id, batch_id, train_cost[0], train_acc[0]))
accs.append(train_acc[0]) # 记录准确率
costs.append(train_cost[0]) # 记录损失值
batches.append(times) # 记录迭代次数

# 训练结束后,保存模型
if not os.path.exists(model_save_dir):
os.makedirs(model_save_dir)
fluid.io.save_inference_model(dirname=model_save_dir,
feeded_var_names=["image"],
target_vars=[predict],
executor=exe)
print("训练保存模型完成!")

# 训练过程可视化
plt.title("training", fontsize=24)
plt.xlabel("iter", fontsize=20)
plt.ylabel("cost/acc", fontsize=20)
plt.plot(batches, costs, color='red', label="Training Cost")
plt.plot(batches, accs, color='green', label="Training Acc")
plt.legend()
plt.grid()
plt.savefig("train.png")
plt.show()
  1. 预测
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from PIL import Image

# 定义执行器
place = fluid.CPUPlace()
infer_exe = fluid.Executor(place)
model_save_dir = "model/fruits/" # 模型保存路径

# 加载数据
def load_img(path):
img = paddle.dataset.image.load_and_transform(path, 128, 128, False).astype("float32")
img = img / 255.0
return img

infer_imgs = [] # 存放要预测图像数据
test_img = "./data/grape_1.png" #待预测图片
infer_imgs.append(load_img(test_img)) #加载图片,并且将图片数据添加到待预测列表
infer_imgs = numpy.array(infer_imgs) # 转换成数组

# 加载模型
infer_program, feed_target_names, fetch_targets = \
fluid.io.load_inference_model(model_save_dir, infer_exe)
# 执行预测
results = infer_exe.run(infer_program, # 执行预测program
feed={feed_target_names[0]: infer_imgs}, # 传入待预测图像数据
fetch_list=fetch_targets) #返回结果
print(results)

result = numpy.argmax(results[0]) # 取出预测结果中概率最大的元素索引值
for k, v in name_dict.items(): # 将类别由数字转换为名称
if result == v: # 如果预测结果等于v, 打印出名称
print("预测结果:", k) # 打印出名称

# 显示待预测的图片
img = Image.open(test_img)
plt.imshow(img)
plt.show()

利用VGG实现图像分类

在水果识别案例第二部分(模型搭建部分)增加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 创建VGG模型
def vgg_bn_drop(image, type_size):
def conv_block(ipt, num_filter, groups, dropouts):
# 创建Convolution2d, BatchNorm, DropOut, Pool2d组
return fluid.nets.img_conv_group(input=ipt, # 输入图像像,[N,C,H,W]格式
pool_stride=2, # 池化步长值
pool_size=2, # 池化区域大小
conv_num_filter=[num_filter] * groups, #卷积核数量
conv_filter_size=3, # 卷积核大小
conv_act="relu", # 激活函数
conv_with_batchnorm=True,#是否使用batch normal
pool_type="max") # 池化类型
conv1 = conv_block(image, 64, 2, [0.0, 0]) # 最后一个参数个数和组数量相对应
conv2 = conv_block(conv1, 128, 2, [0.0, 0])
conv3 = conv_block(conv2, 256, 3, [0.0, 0.0, 0.0])
conv4 = conv_block(conv3, 512, 3, [0.0, 0.0, 0.0])
conv5 = conv_block(conv4, 512, 3, [0.0, 0.0, 0.0])

drop = fluid.layers.dropout(x=conv5, dropout_prob=0.2) # 待调整
fc1 = fluid.layers.fc(input=drop, size=512, act=None)

bn = fluid.layers.batch_norm(input=fc1, act="relu") # batch normal
drop2 = fluid.layers.dropout(x=bn, dropout_prob=0.0)
fc2 = fluid.layers.fc(input=drop2, size=512, act=None)
predict = fluid.layers.fc(input=fc2, size=type_size, act="softmax")

return predict

将创建网络部分改为以下代码即可:

1
2
# 调用上面的函数创建VGG
predict = vgg_bn_drop(image=image, type_size=5) # type_size和水果类别一致

中文文本分类

  1. 数据预处
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# 中文资讯分类示例
# 任务:根据样本,训练模型,将新的文本划分到正确的类别
'''
数据来源:从网站上爬取56821条中文新闻摘要
数据类容:包含10类(国际、文化、娱乐、体育、财经、汽车、教育、科技、房产、证券)
'''

############################# 数据预处理 ##############################
import os
from multiprocessing import cpu_count
import numpy as np
import paddle
import paddle.fluid as fluid

# 定义公共变量
data_root = "data/news_classify/" # 数据集所在目录
data_file = "news_classify_data.txt" # 原始样本文件名
test_file = "test_list.txt" # 测试集文件名称
train_file = "train_list.txt" # 训练集文件名称
dict_file = "dict_txt.txt" # 编码后的字典文件

data_file_path = data_root + data_file # 样本文件完整路径
dict_file_path = data_root + dict_file # 字典文件完整路径
test_file_path = data_root + test_file # 测试集文件完整路径
train_file_path = data_root + train_file # 训练集文件完整路径

# 生成字典文件:把每个字编码成一个数字,并存入文件中
def create_dict():
dict_set = set() # 集合,去重
with open(data_file_path, "r", encoding="utf-8") as f: # 打开原始样本文件
lines = f.readlines() # 读取所有的行

# 遍历每行
for line in lines:
title = line.split("_!_")[-1].replace("\n", "") #取出标题部分,并取出换行符
for w in title: # 取出标题部分每个字
dict_set.add(w) # 将每个字存入集合进行去重

# 遍历集合,每个字分配一个编码
dict_list = []
i = 0 # 计数器
for s in dict_set:
dict_list.append([s, i]) # 将"文字,编码"键值对添加到列表中
i += 1

dict_txt = dict(dict_list) # 将列表转换为字典
end_dict = {"<unk>": i} # 未知字符
dict_txt.update(end_dict) # 将未知字符编码添加到字典中

# 将字典保存到文件中
with open(dict_file_path, "w", encoding="utf-8") as f:
f.write(str(dict_txt)) # 将字典转换为字符串并存入文件

print("生成字典完成.")

# 对一行标题进行编码
def line_encoding(title, dict_txt, label):
new_line = "" # 返回的结果
for w in title:
if w in dict_txt: # 如果字已经在字典中
code = str(dict_txt[w]) # 取出对应的编码
else:
code = str(dict_txt["<unk>"]) # 取未知字符的编码
new_line = new_line + code + "," # 将编码追加到新的字符串后

new_line = new_line[:-1] # 去掉最后一个逗号
new_line = new_line + "\t" + label + "\n" # 拼接成一行,标题和标签用\t分隔
return new_line


# 对原始样本进行编码,对每个标题的每个字使用字典中编码的整数进行替换
# 产生编码后的句子,并且存入测试集、训练集
def create_data_list():
# 清空测试集、训练集文件
with open(test_file_path, "w") as f:
pass
with open(train_file_path, "w") as f:
pass

# 打开原始样本文件,取出标题部分,对标题进行编码
with open(dict_file_path, "r", encoding="utf-8") as f_dict:
# 读取字典文件中的第一行(只有一行),通过调用eval函数转换为字典对象
dict_txt = eval(f_dict.readlines()[0])

with open(data_file_path, "r", encoding="utf-8") as f_data:
lines = f_data.readlines()

# 取出标题并编码
i = 0
for line in lines:
words = line.replace("\n", "").split("_!_") # 拆分每行
label = words[1] # 分类
title = words[3] # 标题

new_line = line_encoding(title, dict_txt, label) # 对标题进行编码
if i % 10 == 0: # 每10笔写一笔测试集文件
with open(test_file_path, "a", encoding="utf-8") as f:
f.write(new_line)
else: # 写入训练集
with open(train_file_path, "a", encoding="utf-8") as f:
f.write(new_line)
i += 1
print("生成测试集、训练集结束.")

create_dict() # 生成字典
create_data_list() # 生成训练集、测试集
  1. 模型训练与评估
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
140
141
142
143
144
145
146
147
148
149
# 读取字典文件,并返回字典长度
def get_dict_len(dict_path):
with open(dict_path, "r", encoding="utf-8") as f:
line = eval(f.readlines()[0]) # 读取字典文件内容,并返回一个字典对象

return len(line.keys())


# 定义data_mapper,将reader读取的数据进行二次处理
# 将传入的字符串转换为整型并返回
def data_mapper(sample):
data, label = sample # 将sample元组拆分到两个变量
# 拆分句子,将每个编码转换为数字, 并存入一个列表中
val = [int(w) for w in data.split(",")]
return val, int(label) # 返回整数列表,标签(转换成整数)


# 定义reader
def train_reader(train_file_path):
def reader():
with open(train_file_path, "r") as f:
lines = f.readlines() # 读取所有的行
np.random.shuffle(lines) # 打乱所有样本

for line in lines:
data, label = line.split("\t") # 拆分样本到两个变量中
yield data, label

return paddle.reader.xmap_readers(data_mapper, # reader读取的数据进行下一步处理函数
reader, # 读取样本的reader
cpu_count(), # 线程数
1024) # 缓冲区大小


# 读取测试集reader
def test_reader(test_file_path):
def reader():
with open(test_file_path, "r") as f:
lines = f.readlines()

for line in lines:
data, label = line.split("\t")
yield data, label

return paddle.reader.xmap_readers(data_mapper,
reader,
cpu_count(),
1024)


# 定义网络
def CNN_net(data, dict_dim, class_dim=10, emb_dim=128, hid_dim=128, hid_dim2=98):
# embedding(词嵌入层):生成词向量,得到一个新的粘稠的实向量
# 以使用较少的维度,表达更丰富的信息
emb = fluid.layers.embedding(input=data, size=[dict_dim, emb_dim])

# 并列两个卷积、池化层
conv1 = fluid.nets.sequence_conv_pool(input=emb, # 输入,上一个词嵌入层的输出作为输入
num_filters=hid_dim, # 卷积核数量
filter_size=3, # 卷积核大小
act="tanh", # 激活函数
pool_type="sqrt") # 池化类型

conv2 = fluid.nets.sequence_conv_pool(input=emb, # 输入,上一个词嵌入层的输出作为输入
num_filters=hid_dim2, # 卷积核数量
filter_size=4, # 卷积核大小
act="tanh", # 激活函数
pool_type="sqrt") # 池化类型
output = fluid.layers.fc(input=[conv1, conv2], # 输入
size=class_dim, # 输出类别数量
act="softmax") # 激活函数
return output

# 定义模型、训练、评估、保存
model_save_dir = "model/news_classify/" # 模型保存路径

words = fluid.layers.data(name="words", shape=[1], dtype="int64",
lod_level=1) # 张量层级
label = fluid.layers.data(name="label", shape=[1], dtype="int64")

# 获取字典长度
dict_dim = get_dict_len(dict_file_path)
# 调用函数创建CNN
model = CNN_net(words, dict_dim)
# 定义损失函数
cost = fluid.layers.cross_entropy(input=model, # 预测结果
label=label) # 真实结果
avg_cost = fluid.layers.mean(cost) # 求损失函数均值
# 准确率
acc = fluid.layers.accuracy(input=model, # 预测结果
label=label) # 真实结果
# 克隆program用于模型测试评估
# for_test如果为True,会少一些优化
test_program = fluid.default_main_program().clone(for_test=True)
# 定义优化器
optimizer = fluid.optimizer.AdagradOptimizer(learning_rate=0.001)
optimizer.minimize(avg_cost)

# 定义执行器
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())

# 准备数据
tr_reader = train_reader(train_file_path)
batch_train_reader = paddle.batch(reader=tr_reader, batch_size=128)

ts_reader = test_reader(test_file_path)
batch_test_reader = paddle.batch(reader=ts_reader, batch_size=128)

feeder = fluid.DataFeeder(place=place, feed_list=[words, label]) # feeder

# 开始训练
for pass_id in range(20):
for batch_id, data in enumerate(batch_train_reader()):
train_cost, train_acc = exe.run(program=fluid.default_main_program(),
feed=feeder.feed(data), # 喂入数据
fetch_list=[avg_cost, acc]) # 要获取的结果
# 打印
if batch_id % 100 == 0:
print("pass_id:%d, batch_id:%d, cost:%f, acc:%f" %
(pass_id, batch_id, train_cost[0], train_acc[0]))

# 每轮次训练完成后,进行模型评估
test_costs_list = [] # 存放所有的损失值
test_accs_list = [] # 存放准确率

for batch_id, data in enumerate(batch_test_reader()): # 读取一个批次测试数据
test_cost, test_acc = exe.run(program=test_program, # 执行test_program
feed=feeder.feed(data), # 喂入测试数据
fetch_list=[avg_cost, acc]) # 要获取的结果
test_costs_list.append(test_cost[0]) # 记录损失值
test_accs_list.append(test_acc[0]) # 记录准确率

# 计算平均准确率和损失值
avg_test_cost = sum(test_costs_list) / len(test_costs_list)
avg_test_acc = sum(test_accs_list) / len(test_accs_list)

print("pass_id:%d, test_cost:%f, test_acc:%f" %
(pass_id, avg_test_cost, avg_test_acc))

# 保存模型
if not os.path.exists(model_save_dir):
os.makedirs(model_save_dir)
fluid.io.save_inference_model(model_save_dir, # 模型保存路径
feeded_var_names=[words.name], # 使用模型时需传入的参数
target_vars=[model], # 预测结果
executor=exe) # 执行器
print("模型保存完成.")
  1. 预测
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
model_save_dir = "model/news_classify/"

def get_data(sentence):
# 读取字典中的内容
with open(dict_file_path, "r", encoding="utf-8") as f:
dict_txt = eval(f.readlines()[0])

keys = dict_txt.keys()
ret = [] # 编码结果
for s in sentence: # 遍历句子
if not s in keys: # 字不在字典中,取未知字符
s = "<unk>"
ret.append(int(dict_txt[s]))

return ret

# 创建执行器
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())

print("加载模型")
infer_program, feeded_var_names, target_var = \
fluid.io.load_inference_model(dirname=model_save_dir, executor=exe)

# 生成测试数据
texts = []
data1 = get_data("在获得诺贝尔文学奖7年之后,莫言15日晚间在山西汾阳贾家庄如是说")
data2 = get_data("综合'今日美国'、《世界日报》等当地媒体报道,芝加哥河滨警察局表示")
data3 = get_data("中国队无缘2020年世界杯")
data4 = get_data("中国人民银行今日发布通知,降低准备金率,预计释放4000亿流动性")
data5 = get_data("10月20日,第六届世界互联网大会正式开幕")
data6 = get_data("同一户型,为什么高层比低层要贵那么多?")
data7 = get_data("揭秘A股周涨5%资金动向:追捧2类股,抛售600亿香饽饽")
data8 = get_data("宋慧乔陷入感染危机,前夫宋仲基不戴口罩露面,身处国外神态轻松")
data9 = get_data("此盆栽花很好养,花美似牡丹,三季开花,南北都能养,很值得栽培")#不属于任何一个类别

texts.append(data1)
texts.append(data2)
texts.append(data3)
texts.append(data4)
texts.append(data5)
texts.append(data6)
texts.append(data7)
texts.append(data8)
texts.append(data9)

# 获取每个句子词数量
base_shape = [[len(c) for c in texts]]
# 生成数据
tensor_words = fluid.create_lod_tensor(texts, base_shape, place)
# 执行预测
result = exe.run(program=infer_program,
feed={feeded_var_names[0]: tensor_words}, # 待预测的数据
fetch_list=target_var)

# print(result)

names = ["文化", "娱乐", "体育", "财经", "房产", "汽车", "教育", "科技", "国际", "证券"]

# 获取最大值的索引
for i in range(len(texts)):
lab = np.argsort(result)[0][i][-1] # 取出最大值的元素下标
print("预测结果:%d, 名称:%s, 概率:%f" % (lab, names[lab], result[0][i][lab]))

中文情绪分析

  1. 数据预处理与模型训练
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
140
141
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
168
169
170
171
172
173
174
175
176
177
178
# 中文情绪分析示例:数据预处理部分
''' 数据集介绍
中文酒店评论,7766笔数据,分为正面、负面评价
'''
import paddle
import paddle.dataset.imdb as imdb
import paddle.fluid as fluid
import numpy as np
import os
import random
from multiprocessing import cpu_count

# 数据预处理,将中文文字解析出来,并进行编码转换为数字,每一行文字存入数组
mydict = {} # 存放出现的字及编码,格式: 好,1
code = 1
data_file = "data/hotel_discuss2.csv" # 原始样本路径
dict_file = "data/hotel_dict.txt" # 字典文件路径
encoding_file = "data/hotel_encoding.txt" # 编码后的样本文件路径
puncts = " \n" # 要剔除的标点符号列表

with open(data_file, "r", encoding="utf-8-sig") as f:
for line in f.readlines():
# print(line)
trim_line = line.strip()
for ch in trim_line:
if ch in puncts: # 符号不参与编码
continue

if ch in mydict: # 已经在编码字典中
continue
elif len(ch) <= 0:
continue
else: # 当前文字没在字典中
mydict[ch] = code
code += 1
code += 1
mydict["<unk>"] = code # 未知字符

# 循环结束后,将字典存入字典文件
with open(dict_file, "w", encoding="utf-8-sig") as f:
f.write(str(mydict))
print("数据字典保存完成!")


# 将字典文件中的数据加载到mydict字典中
def load_dict():
with open(dict_file, "r", encoding="utf-8-sig") as f:
lines = f.readlines()
new_dict = eval(lines[0])
return new_dict

# 对评论数据进行编码
new_dict = load_dict() # 调用函数加载
with open(data_file, "r", encoding="utf-8-sig") as f:
with open(encoding_file, "w", encoding="utf-8-sig") as fw:
for line in f.readlines():
label = line[0] # 标签
remark = line[1:-1] # 评论

for ch in remark:
if ch in puncts: # 符号不参与编码
continue
else:
fw.write(str(mydict[ch]))
fw.write(",")
fw.write("\t" + str(label) + "\n") # 写入tab分隔符、标签、换行符

print("数据预处理完成")

# 获取字典的长度
def get_dict_len(dict_path):
with open(dict_path, 'r', encoding='utf-8-sig') as f:
lines = f.readlines()
new_dict = eval(lines[0])

return len(new_dict.keys())

# 创建数据读取器train_reader和test_reader
# 返回评论列表和标签
def data_mapper(sample):
dt, lbl = sample
val = [int(word) for word in dt.split(",") if word.isdigit()]
return val, int(lbl)

# 随机从训练数据集文件中取出一行数据
def train_reader(train_list_path):
def reader():
with open(train_list_path, "r", encoding='utf-8-sig') as f:
lines = f.readlines()
np.random.shuffle(lines) # 打乱数据

for line in lines:
data, label = line.split("\t")
yield data, label

# 返回xmap_readers, 能够使用多线程方式读取数据
return paddle.reader.xmap_readers(data_mapper, # 映射函数
reader, # 读取数据内容
cpu_count(), # 线程数量
1024) # 读取数据队列大小

# 定义LSTM网络
def lstm_net(ipt, input_dim):
ipt = fluid.layers.reshape(ipt, [-1, 1],
inplace=True) # 是否替换,True则表示输入和返回是同一个对象
# 词嵌入层
emb = fluid.layers.embedding(input=ipt, size=[input_dim, 128], is_sparse=True)

# 第一个全连接层
fc1 = fluid.layers.fc(input=emb, size=128)

# 第一分支:LSTM分支
lstm1, _ = fluid.layers.dynamic_lstm(input=fc1, size=128)
lstm2 = fluid.layers.sequence_pool(input=lstm1, pool_type="max")

# 第二分支
conv = fluid.layers.sequence_pool(input=fc1, pool_type="max")

# 输出层:全连接
out = fluid.layers.fc([conv, lstm2], size=2, act="softmax")

return out

# 定义输入数据,lod_level不为0指定输入数据为序列数据
dict_len = get_dict_len(dict_file) # 获取数据字典长度
rmk = fluid.layers.data(name="rmk", shape=[1], dtype="int64", lod_level=1)
label = fluid.layers.data(name="label", shape=[1], dtype="int64")
# 定义长短期记忆网络
model = lstm_net(rmk, dict_len)

# 定义损失函数,情绪判断实际是一个分类任务,使用交叉熵作为损失函数
cost = fluid.layers.cross_entropy(input=model, label=label)
avg_cost = fluid.layers.mean(cost) # 求损失值平均数
# layers.accuracy接口,用来评估预测准确率
acc = fluid.layers.accuracy(input=model, label=label)

# 定义优化方法
# Adagrad(自适应学习率,前期放大梯度调节,后期缩小梯度调节)
optimizer = fluid.optimizer.AdagradOptimizer(learning_rate=0.001)
opt = optimizer.minimize(avg_cost)

# 定义网络
# place = fluid.CPUPlace()
place = fluid.CUDAPlace(0)
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program()) # 参数初始化

# 定义reader
reader = train_reader(encoding_file)
batch_train_reader = paddle.batch(reader, batch_size=128)

# 定义输入数据的维度,数据的顺序是一条句子数据对应一个标签
feeder = fluid.DataFeeder(place=place, feed_list=[rmk, label])

for pass_id in range(40):
for batch_id, data in enumerate(batch_train_reader()):
train_cost, train_acc = exe.run(program=fluid.default_main_program(),
feed=feeder.feed(data),
fetch_list=[avg_cost, acc])

if batch_id % 20 == 0:
print("pass_id: %d, batch_id: %d, cost: %0.5f, acc:%.5f" %
(pass_id, batch_id, train_cost[0], train_acc))

print("模型训练完成......")

# 保存模型
model_save_dir = "model/chn_emotion_analyses.model"
if not os.path.exists(model_save_dir):
print("create model path")
os.makedirs(model_save_dir)

fluid.io.save_inference_model(model_save_dir, # 保存路径
feeded_var_names=[rmk.name],
target_vars=[model],
executor=exe) # Executor

print("模型保存完成, 保存路径: ", model_save_dir)
  1. 预测
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import paddle
import paddle.fluid as fluid
import numpy as np
import os
import random
from multiprocessing import cpu_count

data_file = "data/hotel_discuss2.csv"
dict_file = "data/hotel_dict.txt"
encoding_file = "data/hotel_encoding.txt"
model_save_dir = "model/chn_emotion_analyses.model"

def load_dict():
with open(dict_file, "r", encoding="utf-8-sig") as f:
lines = f.readlines()
new_dict = eval(lines[0])
return new_dict

# 根据字典对字符串进行编码
def encode_by_dict(remark, dict_encoded):
remark = remark.strip()
if len(remark) <= 0:
return []

ret = []
for ch in remark:
if ch in dict_encoded:
ret.append(dict_encoded[ch])
else:
ret.append(dict_encoded["<unk>"])

return ret


# 编码,预测
lods = []
new_dict = load_dict()
lods.append(encode_by_dict("总体来说房间非常干净,卫浴设施也相当不错,交通也比较便利", new_dict))
lods.append(encode_by_dict("酒店交通方便,环境也不错,正好是我们办事地点的旁边,感觉性价比还可以", new_dict))
lods.append(encode_by_dict("设施还可以,服务人员态度也好,交通还算便利", new_dict))
lods.append(encode_by_dict("酒店服务态度极差,设施很差", new_dict))
lods.append(encode_by_dict("我住过的最不好的酒店,以后决不住了", new_dict))
lods.append(encode_by_dict("说实在的我很失望,我想这家酒店以后无论如何我都不会再去了", new_dict))

# 获取每句话的单词数量
base_shape = [[len(c) for c in lods]]

# 生成预测数据
place = fluid.CPUPlace()
infer_exe = fluid.Executor(place)
infer_exe.run(fluid.default_startup_program())

tensor_words = fluid.create_lod_tensor(lods, base_shape, place)

infer_program, feed_target_names, fetch_targets = fluid.io.load_inference_model(dirname=model_save_dir, executor=infer_exe)
# tvar = np.array(fetch_targets, dtype="int64")
results = infer_exe.run(program=infer_program,
feed={feed_target_names[0]: tensor_words},
fetch_list=fetch_targets)

# 打印每句话的正负面预测概率
for i, r in enumerate(results[0]):
print("负面: %0.5f, 正面: %0.5f" % (r[0], r[1]))