PaddlePaddle / Paddle

PArallel Distributed Deep LEarning: Machine Learning Framework from Industrial Practice (『飞桨』核心框架,深度学习&机器学习高性能单机、分布式训练和跨平台部署)
http://www.paddlepaddle.org/
Apache License 2.0
22.14k stars 5.56k forks source link

请问在训练过程如何在开发集上做自定义的评价 #7716

Closed fseasy closed 6 years ago

fseasy commented 6 years ago

背景

目前在做句子打分(排序)模型,希望在开发集上算一个NDCG分数。

当前paddle在训练过程中做评价的方法

我查看了一些示例代码,感觉基本是这么做的:

trainer = paddle.trainer.SGD(
        cost=model.cost,
        parameters=params,
        update_equation=optimizer,
        **extra_layers=model.eval** # define extra_layers
 )

# devel
result = trainer.test(
                reader=paddle.batch(
                data_generator.train_reader(test_file_list),
                batch_size=conf.batch_size),
                feeding=feeding)

print("Test %d, Cost %f, Eval %s" %
                  (event.pass_id, result.cost, 
                   **result.metrics** # 评价值
                  ))

其中 extra_layers 定义里是paddle.v2.evaluators 预先定义的值

问题

NDCG的评价不在evaluators中,也就是需要做自定义的评价,该如何做呢? 此外,trainner.test 是否能够给出更加详细的API解释呢

qingqing01 commented 6 years ago
  1. 如何在训练中test

    请参考文档示例: https://github.com/PaddlePaddle/models/blob/develop/ltr/train.py#L94

  2. trainer.test接口文档

    请参考http://www.paddlepaddle.org/docs/develop/documentation/zh/api/v2/run_logic.html#trainer 中 的test()接口

  3. NDCG计算

    我看LambdaCost里计算的就是NDCG,并且作为了输出,是否可以直接使用这个?至于如何使用,请参考1中给出的示例。 https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/gserver/layers/CostLayer.cpp#L384

  4. 如何自定义评价方法

    请参考示例文档将需要的层输出,在Python里定义评价函数,调用、计算、输出即可。

fseasy commented 6 years ago

哇,我试了“如何自定义评价方法”,还是不行啊... 我要获取的layer是这样的:

    def _create_all_sent_doc_cos_sim(self, sentence_repr_list, doc_repr):
        """

        calc every sentence to doc cos-similarity
        """

        def _calc_sent_doc_cos_sim(sent_repr, doc_repr):
            cos_sim = paddle.layer.cos_sim(
                name="single_sent_doc_cos_sim",
                a=sent_repr, 
                b=doc_repr
            )
            return cos_sim

        sim_value_vec = paddle.layer.recurrent_group(
            name="calc_sent_doc_sim",
            input=[sentence_repr_list, paddle.layer.StaticInput(doc_repr)],
            step=_calc_sent_doc_cos_sim
        )

我用文档里的方式

            print event.gm.getLayerOutputs("calc_sent_doc_sim")

得到的是这样的内容

{'calc_sent_doc_sim': {'id': None, 'value': None, 'prob': None}}

并没有值啊... @qingqing01 救命...

qingqing01 commented 6 years ago

calc_sent_doc_simpaddle.layer.recurrent_group层,不支持获取该层里面的内容,只能获取recurrent_group他的输出和之外的内容。

这里的recurrent_group的输出single_sent_doc_cos_sim

fseasy commented 6 years ago

哇, 我找到方法啦

  1. 把infer的layer也create出来,
  2. 然后把它作为 trainner 的 extra_layers
  3. 把trainner.test 的reader的batch size设为整个devel数据集大小,使得整个devel数据集只跑一次前向
  4. 利用 event.gm.getLayerOutputs 得到跑完前向后的infer layer的输出结果

哈哈,非常感谢,暂时来看还可以用...

qingqing01 commented 6 years ago

利用 event.gm.getLayerOutputs 得到跑完前向后的infer layer

在你上面列子中infer layer是哪个呢?

fseasy commented 6 years ago

哦,是额外的一个layer哈,就是在得到sim_value_vec 之后,做了一下kmax

        kmax_indices = paddle.layer.kmax_seq_score(
            input=sim_value_vec,
            beam_size=top_k,
            name="kmax_score_indices"
        )

之前想的是直接把全部的sim_value_vec拿到,这样方便自己算NDCG,不过这么拿其实也没有任何的区别

qingqing01 commented 6 years ago

问题已解决,关闭次Issue.