首页 Paddle框架 帖子详情
同一测试数据集,多次预测结果出现不一致,如何解决?
收藏
快速回复
Paddle框架 问答模型训练深度学习 465 0
同一测试数据集,多次预测结果出现不一致,如何解决?
收藏
快速回复
Paddle框架 问答模型训练深度学习 465 0
###### 问题遇到的现象和发生背景 
问题1:
同一测试数据集,多次预测结果出现不一致。

```
模型在测试集上准确率为:12.73%
模型在测试集上准确率为:11.82%


```

问题2:
预测准确率和验证准确率相差甚大,这是何因?

```bash
Epoch 326/500
step 277/277 - loss: 1.0348 - acc: 0.9214 - 77ms/step
save checkpoint at /home/aistudio/data/checkpoint/325
Eval begin...
step 31/31 - loss: 1.6716 - acc: 0.2215 - 60ms/step
Eval samples: 492
Epoch 327/500
step 277/277 - loss: 1.0705 - acc: 0.9225 - 75ms/step
save checkpoint at /home/aistudio/data/checkpoint/326
Eval begin...
step 31/31 - loss: 1.7314 - acc: 0.2236 - 56ms/step


```
###### 问题相关代码,请勿粘贴截图 

```python
class SampleNet(paddle.nn.Layer):
    """
        构建网络Embedding
    """

    def __init__(self, tag_dict: dict, size_dict: dict, emb_size, emb_linear_size, type_size):
        # 继承Model
        super().__init__()
        # 新建一个隐藏层列表,用于存储各字段隐藏层对象
        self.hidden_layers_list = []
        # 定义一个用于记录输出层的输入大小变量,经过一个emb的网络结构就增加该结构的output_dim,以此类推
        out_layer_input_size = 0
        self.relu = paddle.nn.LeakyReLU()  # relu函数,全连接层默认的激活函数是None
        self.drop = paddle.nn.Dropout(p=0.2)  # 正则化方法
        # dict_list为需要处理的数据列表,forward中使用。注意如果前面字段改了,这里也需要改
        self.dict_list = tag_dict.values()
        for tag, tag_method in tag_dict.items():
            # ===== 网络结构方法注册 =====
            # Embedding方法注册
            if tag_method == "emb":
                emb = nn.Embedding(num_embeddings=size_dict[tag], embedding_dim=emb_size)  # 定义多个字段的emb处理方法,添加到一个列表中
                self.hidden_layers_list.append(emb)
            elif tag_method == "norm":
                continue
            elif tag_method is None:
                continue
            else:
                raise Exception(str(tag_method) + "为未知的处理方案")

        self.lstm = nn.LSTM(emb_size, 128, 1)
        self.lin_emb = nn.Linear(in_features=128, out_features=emb_linear_size)
        self.lin_norm1 = nn.Linear(in_features=1, out_features=3)
        self.lin_norm2 = nn.Linear(in_features=3, out_features=1)
        # self.hidden_layers_list.append(hidden_layer)
        # 定义输出层
        self.out_layers = nn.Linear(in_features=1674,  # 注意,如果层数改了,这个地方需要重新计算
                                    out_features=200)
        self.out_layers1 = nn.Linear(in_features=200,
                                     out_features=type_size)

    # 前向推理部分 `*input_data`的`*`表示传入任一数量的变量
    def forward(self, *input_data):
        """

        :param input_data:
        :return:
        """
        layer_list = []  # 用于存储各字段特征结果
        num_id = 0
        for sample_data, tag_method in zip(input_data, self.dict_list):  # 读取前面定义的字段
            tmp = sample_data
            if tag_method == "emb":
                emb = self.hidden_layers_list[num_id]
                tmp = emb(tmp)
                tmp, (_, _) = self.lstm(tmp)
                tmp = self.lin_emb(tmp)
                tmp = self.relu(tmp)
                num_id += 1
            elif tag_method == "norm":
                tmp = self.lin_norm1(tmp)
                tmp = self.relu(tmp)
                tmp = self.lin_norm2(tmp)
                tmp = self.relu(tmp)
            elif tag_method is None:
                continue
            else:
                raise Exception(str(tag_method) + "为未知的处理方案")
            layer_list.append(tensor.flatten(tmp, start_axis=1))  # flatten是因为原始shape为[batch size, 1 , *n], 需要变换为[bs, n]
        # 对所有字段的特征合并
        layers = tensor.concat(layer_list, axis=1)
        # 把特征放入用于输出层的网络
        layers = self.out_layers(layers)
        layers = self.relu(layers)
        layers = self.drop(layers)  # 将42个神经单元随机丢失0.2
        layers = self.out_layers1(layers)
        layers = self.relu(layers)
        layers = paddle.nn.functional.softmax(layers)
        # 返回分类结果
        return layers


```
```python
def emb_train(mtype, mtype_size, is_infer=False, test_batch_size=32, epochs=10, train_batch_size=10,
                      emb_size=128, emb_linear_size=64, num_workers=0):
    """
        emb_train
    :param mtype: 模型类型
    :param mtype_size: 类型值
    :param is_infer: 是否为推理模式
    :param test_batch_size:  若因内存/显存发生报错,请优先调整为1
    :param epochs:  训练多少个循环
    :param train_batch_size:  mini_batch 大小
    :param emb_size:  Embedding特征大小
    :param emb_linear_size:  Embedding后接Linear层神经元数量
    :param num_workers:  线程数
    """
    set_seed(args.seed)
    # 配置训练环境
    USE_MINI_DATA = False  # 默认使用小数据集,此方法可加快模型产出速度,但可能会影响准确率
    USE_GPU = True  # 线性任务GPU可能提升不明显甚至掉速
    print(paddle.CUDAPlace(0))
    paddle.set_device("gpu")
    paddle.disable_static(place=paddle.CUDAPlace(0) if USE_GPU else paddle.CPUPlace())
    # 定义网络输入
    inputs = []
    for tag_name, tag_m in TAGS.items():
        d_type = "float32"
        if tag_m == "emb":
            d_type = "int64"
        if tag_m is None:
            continue
        inputs.append(InputSpec(shape=[-1, 1], dtype=d_type, name=tag_name))
    # 定义Label
    labels = [InputSpec([-1, 1], 'int64', name='label')]

    # 实例化SampleNet以及Reader
    model = paddle.Model(SampleNet(TAGS, get_dict(), emb_size, emb_linear_size, mtype_size), inputs=inputs,
                         labels=labels)

    # 推理部分
    if is_infer:
        infer_reader = ReaderEmb(mtype=mtype, is_infer=is_infer)
        model.load(os.path.join(args.model, mtype + "/final"))
        # 开始推理
        model.prepare()
        infer_output = model.predict(infer_reader, test_batch_size)
        # 获取原始表中的字段并添加推理结果
        result_df = infer_reader.df.loc[:, ["new_issue", "result", "label"]]
        pack = []
        for batch_out in infer_output[0]:
            for sample in batch_out:
                pack.append(np.argmax(sample))
        acc_score = accuracy_score(result_df["label"], pack)
        print('模型在测试集上准确率为:%.2f%%' % (acc_score * 100))
        result_df.rename(columns={'label': 'label_' + mtype}, inplace=True)
        result_df.to_csv(args.result_dir + "result_{}.csv".format(mtype), index=False)
        print("结果文件保存至:", args.result_dir)

    # 直接训练完推理结果
    else:
        # 定义学习率,并加载优化器参数到模型中
        # total_steps = (int(450000) + 1)
        # lr = paddle.fluid.dygraph.PolynomialDecay(0.01, total_steps, 0.001)
        # 获取训练集和测试集数据读取器
        # lr = paddle.optimizer.lr.PolynomialDecay(learning_rate=0.0008, decay_steps=total_steps*3, end_lr = 0.00008),用了这个发现效果更差,干脆不用
        # model.load(os.path.join(SAVE_DIR, "1"))
        # lr = paddle.optimizer.lr.PiecewiseDecay(boundaries=[1, 2], values=[0.001, 0.0001, 0.00001], verbose=True)
        train_reader = ReaderEmb(mtype=mtype, use_mini_train=USE_MINI_DATA)
        val_reader = ReaderEmb(mtype=mtype, use_mini_train=USE_MINI_DATA, is_val=True)
        # 定义优化器
        optimizer = paddle.optimizer.Adam(learning_rate=0.0007, parameters=model.parameters())  # 直接将学习率设置为固定0.0007
        # 模型训练配置
        model.prepare(optimizer, paddle.nn.loss.CrossEntropyLoss(), Accuracy())
        # 开始训练
        model.fit(train_data=train_reader,  # 训练集数据
                  eval_data=val_reader,  # 交叉验证集数据
                  batch_size=train_batch_size,  # Batch size大小
                  epochs=epochs,  # 训练轮数
                  log_freq=1000,  # 日志打印间隔
                  save_dir=args.model + mtype,  # checkpoint保存路径
                  num_workers=num_workers)


```
###### 运行结果及报错内容 
W0707 11:38:35.289726  4444 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 6.1, Driver API Version: 11.6, Runtime API Version: 10.1
CUDAPlace(0)
W0707 11:38:35.314658  4444 device_context.cc:465] device: 0, cuDNN Version: 7.6.
Predict begin...
step 4/4 [==============================] - 49ms/step          
Predict samples: 110
模型在测试集上准确率为:12.73%
结果文件保存至: ./data/result/
--------------
CUDAPlace(0)
W0707 14:30:54.401885  6108 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 6.1, Driver API Version: 11.6, Runtime API Version: 10.1
W0707 14:30:54.423830  6108 device_context.cc:465] device: 0, cuDNN Version: 7.6.
Predict begin...
step 4/4 [==============================] - 58ms/step          
Predict samples: 110
模型在测试集上准确率为:11.82%
结果文件保存至: ./data/result/
0
收藏
回复
需求/bug反馈?一键提issue告诉我们
发现bug?如果您知道修复办法,欢迎提pr直接参与建设飞桨~
在@后输入用户全名并按空格结束,可艾特全站任一用户