forked from moneyDboat/data_grand
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
195 lines (159 loc) · 6 KB
/
main.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
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# -*- coding: utf-8 -*-
"""
@Author : captain
@time : 18-7-10 下午8:42
@ide : PyCharm
"""
import torch
import time
import torch.nn.functional as F
import models
import data
from config import DefaultConfig
import pandas as pd
import os
import fire
from sklearn import metrics
import numpy as np
best_score = 0.0
t1 = time.time()
def main(**kwargs):
args = DefaultConfig()
args.parse(kwargs)
if not torch.cuda.is_available():
args.cuda = False
args.device = None
torch.manual_seed(args.seed) # set random seed for cpu
train_iter, val_iter, test_iter, args.vocab_size, vectors = data.load_data(args)
args.print_config()
global best_score
# init model
model = getattr(models, args.model)(args, vectors)
print(model)
# 模型保存位置
if not os.path.exists(args.save_dir):
os.mkdir(args.save_dir)
save_path = os.path.join(args.save_dir, '{}_{}.pth'.format(args.model, args.id))
if args.cuda:
torch.cuda.set_device(args.device)
torch.cuda.manual_seed(args.seed) # set random seed for gpu
model.cuda()
# 目标函数和优化器
criterion = F.cross_entropy
lr1, lr2 = args.lr1, args.lr2
optimizer = model.get_optimizer(lr1, lr2, args.weight_decay)
for i in range(args.max_epochs):
total_loss = 0.0
correct = 0
total = 0
model.train()
for idx, batch in enumerate(train_iter):
# 训练模型参数
# 使用BatchNorm层时,batch size不能为1
if len(batch) == 1:
continue
text, label = batch.text, batch.label
if args.cuda:
text, label = text.cuda(), label.cuda()
optimizer.zero_grad()
pred = model(text)
loss = criterion(pred, label)
loss.backward()
optimizer.step()
# 更新统计指标
total_loss += loss.item()
predicted = pred.max(1)[1]
total += label.size(0)
correct += predicted.eq(label).sum().item()
if idx % 80 == 79:
print('[{}, {}] loss: {:.3f} | Acc: {:.3f}%({}/{})'.format(i + 1, idx + 1, total_loss / 20,
100. * correct / total, correct, total))
total_loss = 0.0
# 计算再验证集上的分数,并相应调整学习率
f1score = val(model, val_iter, args)
if f1score > best_score:
best_score = f1score
checkpoint = {
'state_dict': model.state_dict(),
'config': args
}
torch.save(checkpoint, save_path)
print('Best tmp model f1score: {}'.format(best_score))
if f1score < best_score:
model.load_state_dict(torch.load(save_path)['state_dict'])
lr1 *= args.lr_decay
lr2 = 2e-4 if lr2 == 0 else lr2 * 0.8
optimizer = model.get_optimizer(lr1, lr2, 0)
print('* load previous best model: {}'.format(best_score))
print('* model lr:{} emb lr:{}'.format(lr1, lr2))
if lr1 < args.min_lr:
print('* training over, best f1 score: {}'.format(best_score))
break
# 保存训练最终的模型
args.best_score = best_score
final_model = {
'state_dict': model.state_dict(),
'config': args
}
best_model_path = os.path.join(args.save_dir, '{}_{}_{}.pth'.format(args.model, args.text_type, best_score))
torch.save(final_model, best_model_path)
print('Best Final Model saved in {}'.format(best_model_path))
# 在测试集上运行模型并生成概率结果和提交结果
if not os.path.exists('result/'):
os.mkdir('result/')
probs, test_pred = test(model, test_iter, args)
result_path = 'result/' + '{}_{}_{}'.format(args.model, args.id, args.best_score)
np.save('{}.npy'.format(result_path), probs)
print('Prob result {}.npy saved!'.format(result_path))
test_pred[['id', 'class']].to_csv('{}.csv'.format(result_path), index=None)
print('Result {}.csv saved!'.format(result_path))
t2 = time.time()
print('time use: {}'.format(t2 - t1))
def test(model, test_data, args):
# 生成测试提交数据csv
# 将模型设为验证模式
model.eval()
result = np.zeros((0,))
probs_list = []
with torch.no_grad():
for batch in test_data:
text = batch.text
if args.cuda:
text = text.cuda()
outputs = model(text)
probs = F.softmax(outputs, dim=1)
probs_list.append(probs.cpu().numpy())
pred = outputs.max(1)[1]
result = np.hstack((result, pred.cpu().numpy()))
# 生成概率文件npy
prob_cat = np.concatenate(probs_list, axis=0)
test = pd.read_csv('/data/yujun/datasets/daguanbei_data/test_set.csv')
test_id = test['id'].copy()
test_pred = pd.DataFrame({'id': test_id, 'class': result})
test_pred['class'] = (test_pred['class'] + 1).astype(int)
return prob_cat, test_pred
def val(model, dataset, args):
# 计算模型在验证集上的分数
# 将模型设为验证模式
model.eval()
acc_n = 0
val_n = 0
predict = np.zeros((0,), dtype=np.int32)
gt = np.zeros((0,), dtype=np.int32)
with torch.no_grad():
for batch in dataset:
text, label = batch.text, batch.label
if args.cuda:
text, label = text.cuda(), label.cuda()
outputs = model(text)
pred = outputs.max(1)[1]
acc_n += (pred == label).sum().item()
val_n += label.size(0)
predict = np.hstack((predict, pred.cpu().numpy()))
gt = np.hstack((gt, label.cpu().numpy()))
acc = 100. * acc_n / val_n
f1score = np.mean(metrics.f1_score(predict, gt, average=None))
print('* Test Acc: {:.3f}%({}/{}), F1 Score: {}'.format(acc, acc_n, val_n, f1score))
return f1score
if __name__ == '__main__':
fire.Fire()