RandolphVI / Text-Pairs-Relation-Classification

About Text Pairs (Sentence Level) Classification (Similarity Modeling) Based on Neural Network.
Apache License 2.0
190 stars 55 forks source link

请问训练好的 w2v 的句子怎么用在这个模型啊 #10

Closed deeplaying closed 3 years ago

deeplaying commented 6 years ago

代码能力比较差,看不大懂

RandolphVI commented 6 years ago

@deeplaying 不出意外的话,你的 w2v 应该是通过 gensim 这个库得到的。应该在训练的时候你就会得到一 xx.model,xx 代表你训练的词向量的超参数维度,如果你设置的 100(或者其他值),只需要检查 train.py 文件开头当中定义的 setting 参数是否符合你的维度。

tf.flags.DEFINE_integer("embedding_dim", 100, "Dimensionality of character embedding (default: 128)")
tf.flags.DEFINE_integer("embedding_type", 1, "The embedding type (default: 1)")

embedding_dim 就代表了你词向量训练的维度。 embedding_type 代表你是否使用 pre-trained 词向量,如果为 1,则表示使用;若为 0,则代表网络不使用你预习训练的词向量,而是随机生成 embedding matrix。(这部分定义在每个 text_model.py 的开头部分)

另外,根据 data_helpers.py 中定义的,你需要将你的词向量模型文件,命名为:'word2vec_' + str(embedding_size) + '.model'格式,例如 word2vec_100.model,并将其放在与代码文件夹同级目录 data/文件夹中。

deeplaying commented 6 years ago

感谢博主,回复的好及时!! 正在看代码,因为数据和博主的不一样,请教关于代码的问题 1、dh 里 data_word2vec() 函数中 front_contentbehind_content 分别带别的是第一个句子和第二个句子吗? 2、如果方便,可以告知 train 是 input_x 张什么样吗, embedding_dim*句子长度吗? 3、bilstm 两个方向是同一个句子还是数据中的句子1+句子2?

RandolphVI commented 6 years ago

@deeplaying

  1. 是的。

  2. 数据集 sample 是以 .json 文件,每一行存储一个样本记录(以 {} 表示一个样本记录),其中数据大概形式为:

第一行: {"front_testid": "xxxxxx", "behind_testid": "xxxxx", "front_features": ["xx", ...,"xx"], "behind_features": ["xx", ...,"xx"], "label": "1"} 第二行: {"front_testid": "xxxxxx", "behind_testid": "xxxxx", "front_features": ["xx", ...,"xx"], "behind_features": ["xx", ...,"xx"], "label": "0"}

front_testidbehind_testid 分别表示句子的 ID,front_featuresbehind_features 分别表示前后句子的分词内容,各自分词都存在一个 list 中,最后 label 就表示前后两者句子是否相似,若相似则为 1,不相似则为 0。所以你如果要直接使用我的代码运行,你需要将自己的数据集处理成上面的形式,同样你也可以自己通过修改 data_helpers.py 中的各个函数来 fit 你的数据集形式。

  1. Bi-lstm 分别对句子 1 与句子 2进行双向的 LSTM 处理,两个句子分别处理完之后,再拼在一起。
deeplaying commented 6 years ago

博主你好,又遇到一个问题。 gensim 训练词向量,按照你的方法得到 vector 短句子经过 pad 后,添加的 0 在 tf.nn.embedding_lookup()会把 vector[0] 这个词的向量带入整个句子中,请问这样没有有问题?

RandolphVI commented 6 years ago

@deeplaying padding 意义就是过长截断,不足补短,常用的做法就是补零,也就是你上述常用的做法。(大家都是这么处理的,应该是没有问题的)

deeplaying commented 6 years ago

假设我的数据其中,一句话分词后['今天', '天气', '很好']

现在要训练词向量,是不是要先把句子 pad 成 ['今天', '天气', '很好', 'pad', 'pad', 'pad'] 再用 gensim 来训练?

我的理解是如果不这样做,训练好再用 0 来 pad,0 在 tf.nn.embedding_lookup() 时会对应一个不是 pad 的词向量。

RandolphVI commented 6 years ago

@deeplaying 首先先解释一下处理顺序。

  1. 先确定语料库,对于你所说的,此时你的任务的语料库就是三个词 [‘今天’, ‘天气’, ‘’很好‘]。
  2. 对这个三词,通过 gensim 来训练,分别得到这三个词的词向量。
  3. 对于你比如指定的 pad 长度为 6,即不足长度为 6 的语句则需要进行补短。此时会先通过 data_helpers.py 中定义的 pad_data() 函数方法,而这个函数里面的核心函数又是定义在 tflearn.data_utilspad_sequences()这个函数,这个函数默认是补全 0。所以应该是 [‘今天’, ‘天气’, ‘’很好‘’, ‘0’, ‘0’, ‘0’] 。
  4. 关键点就是在于 '0' 并没有出现在我们的语料库当中,按理来说应该是没有对应的词向量的。

关于这一点,主要当时我处理的语料库比较大,当时并没有考虑这个问题,程序是正常运行的。

但是,我们现在假设语料库中确确实实没有 ‘0’ 这么一个分词的, Q1. 那么是否在 gensim 生成词向量的时候会对那些未出现的分词单独训练一个词向量?(这是第一点,验证的方法只需要查看,你训练好的词向量模型的词典中的 key 值中是否含有 '0',个人认为应该没有)。 Q2. 那么有没有可能是在 tf.nn.embedding_lookup 的时候,对于那些语料库中的未出现分词同样进行划分处理,从而赋予其一个词向量值。(这点比较有可能,我查阅了一下 tf.nn.embedding_lookup 的用法,虽然有点看不懂,但是其好像是根据 idx 划分的,'0' 虽然未在语料库中出现但是仍然是有 idx,只要存在 idx 就可以划分得到相应的词向量)

个人无法保证哪个猜想是否合理,可能都不对,但是 NLP 预处理的流程是上述四点没错的。如果你对于补全零这件事觉得不太合理,你可以参考这几年比较火的 mask 处理方法。

deeplaying commented 6 years ago

倒不是因为 pad '0' 而觉得不不合理。而是在看了你写的 data_helpers.py 后觉得有疑惑,可能是我没理解。下面几点麻烦确认下

  1. 我看的是 rnn,self.embedding = tf.Variable(pretrained_embedding, trainable=True, dtype=tf.float32, name="embedding")。这里的 pretrained_embedding 用的应该是 load_word2vec_matrix() 返回的 vector 吧?

  2. 然后 vetcor 我自己训练完一个 np.array

  3. pad_sequences() 里不能含有中文,所以 pad 的应该是['今天', '天气', '很好'] 对应的 index [12, 11, 10],然后 pad 之后是 [12, 11, 10, 0, 0, 0]

  4. 我的问题 tf.nn.embedding_lookup() 在查找 0 时会给 vector[0] 这个向量,但是 vector[0] 实际上是另一个词(比如‘下雨’)的词向量。那么 pad 后句子经过 tf.nn.embedding_lookup() 后代表的实际含义可能是 ['今天', '天气', '很好', '下雨', '下雨', '下雨']

以上第4点我的觉得不合理的地方

RandolphVI commented 6 years ago

@deeplaying

  1. 是的
  2. 是的
  3. 是的
  4. 是的

直接对应到 vector[0] 的确是不太合理,但是貌似都是这么做的,其实好像不管补零的是不是 '0',最终都会对应到一个 vector[x] 上面,其可解释性在于,虽然我直接对应一个已有的分词的词向量作为补长的词向量不太合理,但是这个词向量在后面是可以训练的,即会变化的,只是初始值定义的不太严谨。

deeplaying commented 6 years ago

终于搞明白了,再次感谢!!

windsor34 commented 5 years ago

请问有推荐的pre-trained w2v model可以用吗?如果用training data的句子来生成w2v模型,再用training data的label来训练relationship classification 模型,会不会有问题?

RandolphVI commented 5 years ago

@windsor34

不会有问题,nlp 的流程就是如此。 将你需要的语料库(可以是你所说的 training data 的句子)用来生成 w2v 模型,training & test 数据同样是参考该 repo 下文件夹 data 中的 sample 格式。

训练好的 w2v 模型,只要放在与文件夹 data 下(与你的 training & test 数据同级目录),在 train_cnn.py 此训练代码中只要实现指定好 embedding_dim 超参的大小,就可以顺利导入训练好的 w2v 模型用于网络训练,要注意训练好的 w2v 模型的命名格式(参考 data_helpers.py 代码)。

windsor34 commented 5 years ago

谢谢!