PaddlePaddle / PaddleHub

Awesome pre-trained models toolkit based on PaddlePaddle. (400+ models including Image, Text, Audio, Video and Cross-Modal with Easy Inference & Serving)【安全加固,暂停交互,请耐心等待】
https://www.paddlepaddle.org.cn/hub
Apache License 2.0
12.71k stars 2.08k forks source link

。/ #913

Closed Masterkmp closed 3 years ago

Masterkmp commented 4 years ago

请问使用paddlehub可以自定义网络吗,如果可以,应该怎么做,能否提供demo呢?

具体来说,如官方文档给定的 使用预置网络,可以通过hub.TextClassifierTask参数network进行指定不同的网络结构。如下代码表示选择bilstm网络拼接在Transformer类预训练模型之后。 PaddleHub文本分类任务预置网络支持BOW,Bi-LSTM,CNN,DPCNN,GRU,LSTM。指定network应是其中之一。 其中DPCNN网络实现为ACL2017-Deep Pyramid Convolutional Neural Networks for Text Categorization。

那么,用户可以修改这些网络吗,比如,现在想要增加一个GCN网络作为预置网络,应该怎么做呢?

Steffy-zxf commented 4 years ago

你好!可以修改预置网络,预置网络实现可以参考:https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.8/paddlehub/network/classification.py

Masterkmp commented 4 years ago

你好!可以修改预置网络,预置网络实现可以参考:https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.8/paddlehub/network/classification.py

谢谢 回答,我知道你的意思,就是增加一个网络函数在classification.py就行,但是我是在Aistudio上运行的,是直接下载好了paddlehub的整个包,不是在本地跑的。所以不知道怎么重写这个接口(network/classification.py)而不对paddlehub的其余部分不产生影响。 怎么在Aistudio上重写classification.py呢,就像之前重写运行事件一样可以直接改写hook机制,但是组网这里怎么改写呢。

Steffy-zxf commented 4 years ago

另外一种解决方法,可以是继承某个任务Task class,重写_build_net方法,参考文档:https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.8/docs/tutorial/define_task_example.md

Masterkmp commented 4 years ago

另外一种解决方法,可以是继承某个任务Task class,重写_build_net方法

你好,我现在按照这种方法在做,但是遇到了一些问题。 假设现在继承了hub.TextClassifierTask这个类重写一个新的任务子类,代码如下

` class TextClassifierTask_BiLSTMCRF(hub.TextClassifierTask): def _build_net(self): self.seq_len = fluid.layers.data( name="seq_len", shape=[1], dtype='int64', lod_level=0)

    if version_compare(paddle.__version__, "1.6"):
        self.seq_len_used = fluid.layers.squeeze(self.seq_len, axes=[1])
    else:
        self.seq_len_used = self.seq_len

    if self.add_crf:
        unpad_feature = fluid.layers.sequence_unpad(
            self.feature, length=self.seq_len_used)
        hid_dim = 128
        fc0 = fluid.layers.fc(input=unpad_feature, size=hid_dim * 4)
        rfc0 = fluid.layers.fc(input=unpad_feature, size=hid_dim * 4)
        lstm_h, c = fluid.layers.dynamic_lstm(
            input=fc0, size=hid_dim * 4, is_reverse=False)
        rlstm_h, c = fluid.layers.dynamic_lstm(
            input=rfc0, size=hid_dim * 4, is_reverse=True)
        lstm_concat = fluid.layers.concat(input=[lstm_h, rlstm_h], axis=1)
        self.emission = fluid.layers.fc(
            size=self.num_classes,
            input=lstm_concat,
            param_attr=fluid.ParamAttr(
                initializer=fluid.initializer.Uniform(low=-0.1, high=0.1),
                regularizer=fluid.regularizer.L2DecayRegularizer(
                    regularization_coeff=1e-4)))
        size = self.emission.shape[1]
        fluid.layers.create_parameter(
            shape=[size + 2, size], dtype=self.emission.dtype, name='crfw')
        self.ret_infers = fluid.layers.crf_decoding(
            input=self.emission, param_attr=fluid.ParamAttr(name='crfw'))
        ret_infers = fluid.layers.assign(self.ret_infers)
        return [ret_infers]
    else:
        self.logits = fluid.layers.fc(
            input=self.feature,
            size=self.num_classes,
            num_flatten_dims=2,
            param_attr=fluid.ParamAttr(
                name="cls_seq_label_out_w",
                initializer=fluid.initializer.TruncatedNormal(scale=0.02)),
            bias_attr=fluid.ParamAttr(
                name="cls_seq_label_out_b",
                initializer=fluid.initializer.Constant(0.)))

        self.ret_infers = fluid.layers.reshape(
            x=fluid.layers.argmax(self.logits, axis=2), shape=[-1, 1])

        logits = self.logits
        logits = fluid.layers.flatten(logits, axis=2)
        logits = fluid.layers.softmax(logits)
        self.num_labels = logits.shape[1]
        return [logits]`

继承完开始自定义task了,代码如下 ` task_test_new_net=TextClassifierTask_BiLSTMCRF( data_reader=reader, feed_list=feed_list, num_classes=dataset.num_labels,

**feature=?,
token_feature=?,
network='?',
config=config,**

metrics_choices=["default"])

**上面加粗的代码不知道怎么写了,按照官方文档参考:** Use "pooled_output" for classification tasks on an entire sentence.用来直接微调的特征 pooled_output = outputs["pooled_output"] Use "sequence_output" for token-level output.,用来作拼接net用的特征 token_feature_output = outputs["sequence_output"]) ` 用paddlehub拼接其他的网络,那么应该使用token_feature,微调的话用的feature。你刚刚说的这种"继承某个任务Task class,重写_build_net方法"是更改了原本微调部分全链接层的代码,但是作为拼接网络似乎得用token_feature特征,而微调的那部分默认代码用的是feature特征。请问这里后续应该怎么写呢?

后序代码试着这么写的: task_test_new_net=TextClassifierTask_BiLSTMCRF( data_reader=reader, feed_list=feed_list, num_classes=dataset.num_labels, feature=token_feature_output, config=config, metrics_choices=["acc"]) 运行报错了 如下: ---------------------------------------------------------------------------AssertionError Traceback (most recent call last)<ipython-input-4-b80920a58635> in <module> 5 feature=token_feature_output, 6 config=config, ----> 7 metrics_choices=["acc"]) 8 9 #直接微调 /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddlehub/finetune/task/classifier_task.py in __init__(self, num_classes, dataset, feed_list, data_reader, feature, token_feature, network, startup_program, config, hidden_units, metrics_choices) 229 assert len( 230 feature.shape --> 231 ) == 2, 'When you do not use network, the parameter feture must be the sentence-level feature ([batch_size, hidden_size]), such as the pooled_output of ERNIE, BERT, RoBERTa and ELECTRA module.' 232 233 self.network = network AssertionError: When you do not use network, the parameter feture must be the sentence-level feature ([batch_size, hidden_size]), such as the pooled_output of ERNIE, BERT, RoBERTa and ELECTRA module.

Masterkmp commented 4 years ago

另外一种解决方法,可以是继承某个任务Task class,重写_build_net方法,参考文档:https://github.com/PaddlePaddle/PaddleHub/blob/release/v1.8/docs/tutorial/define_task_example.md 你好,能否帮忙写一个可运行的demo,我参考后改写. 官方组网你给的参考文档有一定出入,且没有给出后面具体怎么使用的demo.而且这里组网用的特征是pooled_output而不是sequence_output。 关于feature如下: feature(Variable): thefeaturewill be used to classify texts. It must be the sentence-level feature, shape as [-1, emb_size].Token_featureandfeaturecouldn't be setted at the same time. One of them must be setted as not None. Default None. token_feature(Variable): thefeaturewill be used to connect the pre-defined network. It must be the token-level feature, shape as [-1, seq_len, emb_size]. Default None.

Steffy-zxf commented 4 years ago

通过自定义Task,只需要在demo中将PaddleHub 内置的Task,替换成自定义Task即可,demo可以参考:https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.8/demo/text_classification

同时可以参考issue: https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.8/demo/text_classification

Masterkmp commented 4 years ago

通过自定义Task,只需要在demo中将PaddleHub 内置的Task,替换成自定义Task即可,demo可以参考:https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.8/demo/text_classification

同时可以参考issue: https://github.com/PaddlePaddle/PaddleHub/tree/release/v1.8/demo/text_classification

你好,你发的这两链接是一样的,哪个issue? 另外,我已经参考了文档,但是报错了,具体请您看一下上面哦

Steffy-zxf commented 4 years ago

可以参考这个issue:https://github.com/PaddlePaddle/PaddleHub/issues/476

用paddlehub拼接其他的网络,那么应该使用token_feature,微调的话用的feature。你刚刚说的这种"继承某个任务Task class,重写_build_net方法"是更改了原本微调部分全链接层的代码,但是作为拼接网络似乎得用token_feature特征,而微调的那部分默认代码用的是feature特征。请问这里后续应该怎么写呢?

  1. token_feature 是指的是token-level的特征,比如,ernie 的 sequence_out 就是token-level的特征,shape是[batch_size, max_seq_len, emb_size]; feature 是指 sentence-level的特征, 比如 ernie 的 pooled_out 就是sentence-level的特征,shape是[batch_size, hidden_size]。
  2. 重写_build_net方法 可以 搭建任意你想要组建的网络结构,只需要和父类Task的_build_net方法输入输出参数类型保持一致。
Masterkmp commented 4 years ago

可以参考这个issue:#476

用paddlehub拼接其他的网络,那么应该使用token_feature,微调的话用的feature。你刚刚说的这种"继承某个任务Task class,重写_build_net方法"是更改了原本微调部分全链接层的代码,但是作为拼接网络似乎得用token_feature特征,而微调的那部分默认代码用的是feature特征。请问这里后续应该怎么写呢?

1. token_feature 是指的是token-level的特征,比如,ernie 的 sequence_out 就是token-level的特征,shape是[batch_size, max_seq_len, emb_size]; feature 是指 sentence-level的特征, 比如 ernie 的 pooled_out 就是sentence-level的特征,shape是[batch_size, hidden_size]。

2. 重写_build_net方法 可以 搭建任意你想要组建的网络结构,只需要和父类Task的_build_net方法输入输出参数类型保持一致。

你好,感谢回复,参考后还是没有弄出来。 我现在通过继承hub.ClassifierTask类,写了一个新的类SD_TextClassifierTask(我现在要在这里面自定义BiLstm),SD_TextClassifierTask的改写参考了"PaddleHub-release-v1.8\PaddleHub-release-v1.8\paddlehub\finetune\task\classifier_task.py"里面的TextClassifierTask类,代码如下: 图片 图片 图片 图片

现在实例化一个task 图片 图片 开始运行下面的代码,然后报错了,如下: 图片 图片 图片 请问应该怎么解决呢?

Steffy-zxf commented 4 years ago

请检查下网络的输入输出的shape,类型是否符合预期。具体问题需要调试看看。

haoyuying commented 3 years ago

Since you haven't replied for more than 3 months, we have closed this issue/pr. If the problem is not solved or there is a follow-up one, please reopen it at any time and we will continue to follow up. 由于您超过三个月未回复,我们将关闭这个issue/pr。 若问题未解决或有后续问题,请随时重新打开,我们会继续跟进。