forked from DoubleXixi/baodu-qinghua
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTorchTestDemo.py
153 lines (133 loc) · 6.2 KB
/
TorchTestDemo.py
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
# coding:utf8
import torch
import torch.nn as nn
import numpy as np
import random
import json
import matplotlib.pyplot as plt
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
"""
基于pytorch框架编写模型训练
实现一个自行构造的找规律(机器学习)任务
规律:x是一个5维向量,如果第1个数>第5个数,则为正样本,反之为负样本
"""
#模型
class TorchModel(nn.Module):
def __init__(self, input_size):
super().__init__()
self.linear = nn.Linear(input_size, 8) # 线性层10-8
self.linear1 = nn.Linear(8, 6) # 线性层8-6
self.linear2 = nn.Linear(6, 4) # 线性层6-4
self.linear3 = nn.Linear(4, 2) # 线性层4-2
self.linear4 = nn.Linear(2, 1) # 线性层2-1
self.activation = torch.sigmoid # sigmoid归一化函数
self.loss = nn.functional.mse_loss # loss函数采用均方差损失
# 当输入真实标签,返回loss值;无真实标签,返回预测值
def forward(self, x, y=None):
x = self.linear(x) # (batch_size, input_size) -> (batch_size, 8)
x1 = self.linear1(x) # (batch_size, input_size) -> (batch_size, 6)
x2 = self.linear2(x1) # (batch_size, input_size) -> (batch_size, 4)
x3 = self.linear3(x2) # (batch_size, input_size) -> (batch_size, 2)
x4 = self.linear4(x3) # (batch_size, input_size) -> (batch_size, 1)
y_pred = self.activation(x4) # (batch_size, 1) -> (batch_size, 1)
if y is not None:
return self.loss(y_pred, y) # 预测值和真实值计算损失
else:
return y_pred # 输出预测结果
# 生成一个样本, 样本的生成方法,代表了我们要学习的规律
# 随机生成一个5维向量,如果第一个值大于第五个值,认为是正样本,反之为负样本
def build_sample():
x = np.random.random(10)
if x[0] > x[9] or x[4] > x[5] :
return x, 1
else:
return x, 0
# 随机生成一批样本
# 正负样本均匀生成
def build_dataset(total_sample_num):
X = []
Y = []
for i in range(total_sample_num):
x, y = build_sample()
X.append(x)
Y.append([y])
return torch.FloatTensor(X), torch.FloatTensor(Y)
# 测试代码
# 用来测试每轮模型的准确率
def evaluate(model):
model.eval()
test_sample_num = 1000
x, y = build_dataset(test_sample_num)
print("本次预测集中共有%d个正样本,%d个负样本" % (sum(y), test_sample_num - sum(y)))
correct, wrong = 0, 0
with torch.no_grad():
y_pred = model(x) # 模型预测
for y_p, y_t in zip(y_pred, y): # 与真实标签进行对比
if float(y_p) < 0.5 and int(y_t) == 0:
correct += 1 # 负样本判断正确
elif float(y_p) >= 0.5 and int(y_t) == 1:
correct += 1 # 正样本判断正确
else:
wrong += 1
print("正确预测个数:%d, 正确率:%f" % (correct, correct / (correct + wrong)))
return correct / (correct + wrong)
def main():
# 配置参数
epoch_num = 100 # 训练轮数
batch_size = 20 # 每次训练样本个数
train_sample = 5000 # 每轮训练总共训练的样本总数
input_size = 10 # 输入向量维度
learning_rate = 0.001 # 学习率
# 建立模型
model = TorchModel(input_size)
# 选择优化器
optim = torch.optim.RAdam(model.parameters(), lr=learning_rate)
log = []
# 创建训练集,正常任务是读取训练集
train_x, train_y = build_dataset(train_sample)
# 训练过程
for epoch in range(epoch_num):
model.train()
watch_loss = []
for batch_index in range(train_sample // batch_size):
x = train_x[batch_index * batch_size : (batch_index + 1) * batch_size]
y = train_y[batch_index * batch_size : (batch_index + 1) * batch_size]
optim.zero_grad() # 梯度归零
loss = model(x, y) # 计算loss
loss.backward() # 计算梯度
optim.step() # 更新权重
watch_loss.append(loss.item())
print("=========\n第%d轮平均loss:%f" % (epoch + 1, np.mean(watch_loss)))
acc = evaluate(model) # 测试本轮模型结果
log.append([acc, float(np.mean(watch_loss))])
# 保存模型
torch.save(model.state_dict(), "model.pth")
# 画图
#print(log)
plt.plot(range(len(log)), [l[0] for l in log], label="acc") # 画acc曲线
plt.plot(range(len(log)), [l[1] for l in log], label="loss") # 画loss曲线
plt.legend()
plt.show()
return
# 使用训练好的模型做预测
def predict(model_path, input_vec):
input_size = 10
model = TorchModel(input_size)
model.load_state_dict(torch.load(model_path)) # 加载训练好的权重
# print(model.state_dict())
model.eval() # 测试模式
with torch.no_grad(): # 不计算梯度
result = model.forward(torch.FloatTensor(input_vec)) # 模型预测
for vec, res in zip(input_vec, result):
print("输入:%s, 预测类别:%d, 概率值:%f" % (vec, round(float(res)), res)) # 打印结果
if __name__ == "__main__":
main()
test_vec = [[0.47889086,0.15229675,0.31082123,0.03504317,0.88920843,0.97889086,0.15229675,0.31082123,0.03504317,0.88920843],
[0.94963533,0.5524256,0.95758807,0.95520434,0.84890681,0.94963533,0.5524256,0.95758807,0.95520434,0.84890681],
[0.78797868,0.67482528,0.13625847,0.34675372,0.99871392,0.78797868,0.67482528,0.13625847,0.34675372,0.99871392],
[0.1349776,0.59416669,0.92579291,0.41567412,0.7358894,0.1349776,0.59416669,0.92579291,0.41567412,0.7358894],
[0.1349776, 0.59416669, 0.92579291, 0.41567412, 0.7358894, 0.1349776, 0.59416669, 0.92579291,0.41567412, 0.7358894],
[0.1349776, 0.59416669, 0.92579291, 0.41567412, 0.7358894, 0.1349776, 0.59416669, 0.92579291,0.41567412, 0.7358894],
[0.1349776, 0.59416669, 0.92579291, 0.41567412, 0.0358894, 0.1349776, 0.59416669, 0.92579291, 0.41567412,0.7358894]]
predict("model.pth", test_vec)