学习THUMT(2):尝试训练一个小型模型(to be continued...)


今天我决定照着UserManual里给出的方法训练一个小型的模型尝试一下,了解一下各个步骤都在做什么。

一些微小的问题

tensorflow-gpu

我首先尝试在自己的电脑上安装tensorflow-gpu。最后我虽然装上了,但却决定不用它了,因为我意识到我的这块普通显卡过于菜了(以至于nvidia-smi不能打印它的具体信息),这么做没什么太大的意义。

PyCharm和virtualenv

目前我的所有Python项目都是通过这两个东西运行的,看起来还不错;可是virtualenv存在一个问题,就是不容易卸载,或者说卸载包的时候可能会出一点问题——反正我卸载tensorflow-gpu再安装tensorflow之后,根本都找不到Module tensorflow了。但这大概不算什么大问题,因为网上的人都说[1],"virtualenv is cheap",如果把当前的环境搞乱了,直接删了新建一个就好。

virtualenv还有一个我之前没有想到的好处。它不止可以管理Python包,还可以管理环境变量。UserManual里要求在$PYTHONPATH里加上项目根路径,我一开始不太理解为什么,后来发现如果不加的话根本就找不到THUMT自己的包。我还以为是PyCharm没有定义好源文件夹的问题或者tensorflow挂了的问题呢。看来我对Python模块化和类编程根本就不是很熟悉……

总之在virtualenv里可以在venv/bin/activate中增加以下命令来修改虚拟环境中的环境变量[2]

1
2
_OLD_PYTHONPATH="$PYTHONPATH"
export PYTHONPATH="/path/to/THUMT:$PYTHONPATH"

然后在deactivate()函数中增加以下内容:

1
export PYTHONPATH="$_OLD_PYTHONPATH"

可以使用printenv PYTHONPATH以查看设置情况。

当然实际上应该写得更复杂一点,activate文件中本身就有设置和取消设置环境变量的例子,这里就先这样好了。

准备数据

语料

UserManual中使用的示例语料来自http://data.statmt.org/wmt17/translation-task/preprocessed/de-en/,是经过预处理的语料。不过这些语料到底经历了怎样的预处理呢……

被预处理完的corpus是这个样子的(取了前5个句子):

Deutsch English
Europäische Kommission - Upcoming events European Commission - Upcoming events
die Nachricht : the news :
die Anmeldung zur Veranstaltung kann vorgenommen werden . registration for the event can be submitted .
Hintergrund : the background :
die folgen dem Vorbild der " Gemeindeversammlung " bzw. lokaler Bürgerforen , bei denen Vertreter der Politik sich mit Bürgerinnen und Bürgern über politische Fragen und anstehende Entscheidungen austauschen . the concept of builds on the model of " town hall meetings " or local fora during which politicians listen and debate with citizens about policies and decisions being taken .

被预处理完的测试数据是这个样子的:

Deutsch English
Gutach : noch mehr Sicherheit für Fußgänger Gutach : increased safety for pedestrians
Sie stehen keine 100 Meter voneinander entfernt : am Dienstag ist in Gutach die neue B 33 @-@ Fußgängerampel am Dorfparkplatz in Betrieb genommen worden - in Sichtweite der älteren Rathausampel . they are not even 100 metres apart : on Tuesday , the new B 33 pedestrian lights in Dorfparkplatz in Gutach became operational - within view of the existing Town Hall traffic lights .
zwei Anlagen so nah beieinander : Absicht oder Schildbürgerstreich ? two sets of lights so close to one another : intentional or just a silly error ?
diese Frage hat Gutachs Bürgermeister gestern klar beantwortet . yesterday , Gutacht 's Mayor gave a clear answer to this question .
" die Rathausampel ist damals installiert worden , weil diese den Schulweg sichert " , erläuterte Eckert gestern . " at the time , the Town Hall traffic lights were installed because this was a school route , " explained Eckert yesterday .

至少可以看出有一部分符号被转义了(@-@),而且符号也进行了分词。

根据prepare.sh,训练数据经过了以下处理:

测试数据是从.sgm格式转换来的,所以前面多一个input-from-sgm,其他的处理都一样。

BPE

然后就是用rsennrich/subword-nmt中提供的脚本对原始语料进行BPE处理。此处我尝试对训练语料(单语大小约800M)跑了一下BPE,发现花了一个多小时,遂放弃,准备把其中一个测试集当做训练集来用。

以及现在subword-nmt这个仓库的使用方式已经有了一些变化,目前推荐的是pip install subword-nmt,然后直接通过包来调用脚本(而不是直接调用脚本):

1
subword-nmt learn-joint-bpe-and-vocab --input {train_file}.L1 {train_file}.L2 -s {num_operations} -o {codes_file} --write-vocabulary {vocab_file}.L1 {vocab_file}.L2

于是得到了BPE编码文件(其中</w>应该表示的是词尾):

2018.11.28 UPDATE:感谢评论区@ao ben指出,BPE编码文件中</w>表达的应该是单词的结尾。阅读了一些代码[5]之后,我想这个文件可能从上到下表示了将词中的字母进行合并的顺序。

1
2
3
4
5
6
7
8
9
10
11
12
#version: 0.2
e n</w>
e r
i n
t h
e r</w>
c h
a n
e n
u n
th e</w>
...

和两种语料上的词汇表:

1
2
3
4
5
6
7
8
9
10
11
12
, 3761
. 2782
die 2067
der 1761
und 1263
&quot; 1156
in 1022
@-@ 710
das 667
zu 645
von 629
... (Deutsch)
1
2
3
4
5
6
7
8
9
10
11
12
the 4290
, 3050
. 2776
of 1700
to 1693
a 1369
in 1291
and 1259
&quot; 1182
@-@ 658
is 615
... (English)

然后用上述得到的BPE编码文件和词汇表对训练集、验证集、测试集的源语言一侧分别进行编码。以训练集为例,此时就得到了一堆这样的东西:

Deutsch Deutsch (BPE)
Gutach : noch mehr Sicherheit für Fußgänger G@@ u@@ t@@ a@@ c@@ h : noch mehr S@@ i@@ c@@ h@@ er@@ h@@ e@@ i@@ t für F@@ u@@ ß@@ g@@ ä@@ n@@ g@@ er
Sie stehen keine 100 Meter voneinander entfernt : am Dienstag ist in Gutach die neue B 33 @-@ Fußgängerampel am Dorfparkplatz in Betrieb genommen worden - in Sichtweite der älteren Rathausampel . Sie s@@ t@@ e@@ h@@ en keine 1@@ 0@@ 0 M@@ e@@ t@@ er v@@ o@@ n@@ ein@@ an@@ der e@@ n@@ t@@ f@@ er@@ n@@ t : am D@@ i@@ e@@ n@@ s@@ t@@ a@@ g ist in G@@ u@@ t@@ a@@ c@@ h die n@@ e@@ u@@ e B 3@@ 3 @-@ F@@ u@@ ß@@ g@@ ä@@ n@@ g@@ er@@ a@@ m@@ p@@ e@@ l am D@@ o@@ r@@ f@@ p@@ a@@ r@@ k@@ p@@ l@@ a@@ t@@ z in B@@ e@@ t@@ r@@ i@@ e@@ b g@@ e@@ n@@ o@@ m@@ m@@ en worden - in S@@ i@@ c@@ h@@ t@@ w@@ e@@ i@@ te der ä@@ l@@ t@@ er@@ en R@@ a@@ t@@ h@@ a@@ u@@ s@@ a@@ m@@ p@@ e@@ l .
zwei Anlagen so nah beieinander : Absicht oder Schildbürgerstreich ? zwei A@@ n@@ l@@ a@@ g@@ en so n@@ a@@ h b@@ e@@ i@@ ein@@ an@@ der : A@@ b@@ s@@ i@@ c@@ h@@ t oder S@@ c@@ h@@ i@@ l@@ d@@ b@@ ü@@ r@@ g@@ er@@ s@@ t@@ r@@ e@@ i@@ c@@ h ?
diese Frage hat Gutachs Bürgermeister gestern klar beantwortet . diese F@@ r@@ a@@ g@@ e hat G@@ u@@ t@@ a@@ c@@ h@@ s B@@ ü@@ r@@ g@@ er@@ m@@ e@@ i@@ s@@ t@@ er ge@@ s@@ t@@ er@@ n k@@ l@@ a@@ r be@@ an@@ t@@ w@@ o@@ r@@ t@@ e@@ t .
&quot; die Rathausampel ist damals installiert worden , weil diese den Schulweg sichert &quot; , erläuterte Eckert gestern . &quot; die R@@ a@@ t@@ h@@ a@@ u@@ s@@ a@@ m@@ p@@ e@@ l ist d@@ a@@ m@@ als i@@ n@@ s@@ t@@ a@@ l@@ l@@ i@@ er@@ t worden , w@@ e@@ i@@ l diese den S@@ c@@ h@@ u@@ l@@ w@@ e@@ g s@@ i@@ c@@ h@@ er@@ t &quot; , er@@ l@@ ä@@ u@@ t@@ er@@ te E@@ c@@ k@@ er@@ t ge@@ s@@ t@@ er@@ n .
English English (BPE)
Gutach : increased safety for pedestrians G@@ u@@ t@@ a@@ c@@ h : i@@ n@@ c@@ re@@ a@@ s@@ e@@ d s@@ a@@ f@@ e@@ t@@ y for p@@ e@@ d@@ e@@ s@@ t@@ r@@ i@@ a@@ n@@ s
they are not even 100 metres apart : on Tuesday , the new B 33 pedestrian lights in Dorfparkplatz in Gutach became operational - within view of the existing Town Hall traffic lights . they are not even 1@@ 0@@ 0 m@@ e@@ t@@ re@@ s a@@ p@@ a@@ r@@ t : on T@@ u@@ e@@ s@@ d@@ a@@ y , the new B 3@@ 3 p@@ e@@ d@@ e@@ s@@ t@@ r@@ i@@ an l@@ i@@ g@@ h@@ t@@ s in D@@ o@@ r@@ f@@ p@@ a@@ r@@ k@@ p@@ l@@ a@@ t@@ z in G@@ u@@ t@@ a@@ c@@ h b@@ e@@ c@@ a@@ m@@ e o@@ p@@ e@@ r@@ a@@ t@@ i@@ o@@ n@@ a@@ l - w@@ i@@ t@@ h@@ in v@@ i@@ e@@ w of the e@@ x@@ i@@ s@@ t@@ ing T@@ o@@ w@@ n H@@ all t@@ r@@ a@@ f@@ f@@ i@@ c l@@ i@@ g@@ h@@ t@@ s .
two sets of lights so close to one another : intentional or just a silly error ? two s@@ e@@ t@@ s of l@@ i@@ g@@ h@@ t@@ s so c@@ l@@ o@@ s@@ e to one a@@ n@@ other : i@@ n@@ t@@ e@@ n@@ t@@ i@@ o@@ n@@ a@@ l or j@@ u@@ s@@ t a s@@ i@@ l@@ l@@ y e@@ r@@ r@@ o@@ r ?
yesterday , Gutacht &apos;s Mayor gave a clear answer to this question . y@@ e@@ s@@ t@@ e@@ r@@ d@@ a@@ y , G@@ u@@ t@@ a@@ c@@ h@@ t &apos;s M@@ a@@ y@@ or g@@ a@@ v@@ e a c@@ l@@ e@@ a@@ r a@@ n@@ s@@ w@@ e@@ r to this q@@ u@@ e@@ s@@ t@@ i@@ on .
&quot; at the time , the Town Hall traffic lights were installed because this was a school route , &quot; explained Eckert yesterday . &quot; at the time , the T@@ o@@ w@@ n H@@ all t@@ r@@ a@@ f@@ f@@ i@@ c l@@ i@@ g@@ h@@ t@@ s were i@@ n@@ s@@ t@@ a@@ l@@ l@@ e@@ d because this was a s@@ c@@ h@@ o@@ o@@ l r@@ o@@ u@@ t@@ e , &quot; e@@ x@@ p@@ l@@ a@@ i@@ n@@ e@@ d E@@ c@@ k@@ e@@ r@@ t y@@ e@@ s@@ t@@ e@@ r@@ d@@ a@@ y .

我猜@@指示的是词中间的分词。显然这不是一个正常的学习状况——因为学习的语料太少,词语出现频率不够,很多常见词都被切成字母了。我猜这将导致最后的测试结果不太像人类语言(如果还能跑出测试结果的话……)。不过可以看出,这个BPE还是学到了一些最常用的词汇的,比如德语的sie,am,ist,diese,den,英语的they,are,other,all等。

shuffle

据说这一步可以提高翻译质量(虽然我目前还不知道为什么)。我之前猜测可能和ensemble有关,不过这一点还需要思考一下。

生成NMT使用的词表

这一步的工作不需要用到之前生成的BPE操作和词表,而是由THUMT里的脚本直接从训练数据中再生成一次词表。我目前还不知道为什么要这么做——当然,这么做肯定没有问题,而且还有通用性。显然里面添加了一些控制字符。

1
2
3
4
5
6
7
8
9
10
11
<pad>
<eos>
<unk>
e@@
i@@
n@@
s@@
t@@
a@@
h@@
... (Deutsch)
1
2
3
4
5
6
7
8
9
10
11
<pad>
<eos>
<unk>
e@@
a@@
i@@
t@@
o@@
r@@
n@@
... (English)

训练

训练的时候主要有这样的一些参数:

  • input:经过BPE和shuffle的训练数据(de+en)
  • vocabulary:通过脚本从经过BPE处理的训练数据中提取的词表(de+en)
  • model:使用的模型(目前使用的是推荐的transformer
  • validation:经过BPE的验证数据(de)
  • references:经过BPE的验证数据(en)
  • parameters:其他超参数
    • batch_size:每个batch训练多少个词
    • device_list:使用哪些显卡进行训练
    • train_steps:迭代次数
    • eval_steps:训练多少步输出一次在验证集上的BLEU值
    • keep_checkpoint_max:最多保留几个中间checkpoint
    • keep_top_checkpoint_max:最多保留几个最佳checkpoint

目前我正在我的垃圾小电脑上用batch_size=400, train_steps=2000的参数训练(毕竟现在训练集只有25万个词),已经输出了两个checkpoint,但它似乎卡在计算模型在验证集上的BLEU值这一步上了……好像验证这一步的确是比较慢的,我打算明天再看到底是TensorFlow卡死了,还是单纯太慢了。

To be continued...

UPDATE:跑了一晚上,终于验证出一个结果了。程序输出如下图:

1
2
3
INFO:tensorflow:BLEU at step 2000: 0.001024
INFO:tensorflow:Copying train/model.ckpt-2000 to train/eval/model.ckpt-2000
INFO:tensorflow:Best score at step 2000: 0.001024

并在train/eval中保留了这个checkpoint。

(0.001,这个BLEU值还真是惊人的低呢……虽然训练过程只花了大约两个小时,验证花了可能得有10个小时……)

测试

下面就可以尝试用训练出的模型对测试集进行翻译了。使用的参数包括:

  • models:模型
  • checkpoints:模型checkpoints位置,可以通过输入多个模型的checkpoints位置进行ensemble
  • input:经过BPE的测试数据(de)
  • output:翻译结果(en)
  • vocabulary:通过脚本从经过BPE处理的训练数据中提取的词表(de+en),需要与训练使用的词表保持一致
  • parameters:其他超参数

垃圾小电脑大约需要1.5小时才能跑完一个batch,不知道一共有多少个batch……

To be continued...

2018.10.8 UPDATE:跑完了,一共94个batch。删除BPE分词之后,得到了这样的东西:

Deutsch English English (Translated)
Obama empfängt Netanyahu Obama receives Netanyahu <unk> Progen<unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk>
das Verhältnis zwischen Obama und Netanyahu ist nicht gerade freundschaftlich . the relationship between Obama and Netanyahu is not exactly friendly . <unk> <unk> staff<unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk>
die beiden wollten über die Umsetzung der internationalen Vereinbarung sowie über Teherans destabilisierende Maßnahmen im Nahen Osten sprechen . the two wanted to talk about the implementation of the international agreement and about Teheran &apos;s destabilising activities in the Middle East . <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk>
bei der Begegnung soll es aber auch um den Konflikt mit den Palästinensern und die diskutierte Zwei @-@ Staaten @-@ Lösung gehen . the meeting was also planned to cover the conflict with the Palestinians and the disputed two state solution . <unk> <unk> <unk> st<unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk>
das Verhältnis zwischen Obama und Netanyahu ist seit Jahren gespannt . relations between Obama and Netanyahu have been strained for years . <unk> <unk> <unk> <unk> st<unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk>

可以看出,这个模型根本什么都没翻译出来。考虑到BPE把词都切成字母了,这一点也可以想象得到。最后可以通过Moses里提供的脚本计算验证集的BLEU值:

1
BLEU = 0.00, 0.0/0.0/0.0/0.0 (BP=1.000, ratio=5.679, hyp_len=372780, ref_len=65647)

虽然我猜BLEU值应该并没有低到严格为0,但是显然已经被四舍五入为0了。简直低破天际。

模型平均和集成

THUMT支持model averaging(把训练过程中生成的部分checkpoint进行平均)和model ensemble(对同一模型的不同训练结果进行ensemble)。以后有时间的话我要去读一下ensemble是怎么实现的。不过现在就不用这些功能了……

可视化

TensorBoard

在训练过程中,train/文件夹下打印出了一个events.out.tfevents文件,可以用TensorBoard进行可视化。

TensorBoard整体示意图(其中只有Graph的内容能看懂)

batch_examples

batch_examples:处理数据

从代码中可知,这个结点在trainer.py中通过调用record.py中的get_input_features函数生成,其中batch_examples函数大概是做了一个将输入数据按长度分块的工作,内部调用了tf.contrib.training.bucket_by_sequence_length函数。

embedding

Transformer结点中显示在左下角的是embedding结点:

embedding:将one hot向量embed成稠密向量

source_embeddingtarget_embedding分别定义于transformer.py/encoding_graphtransformer.py/decoding_graph中,它们并不是Encoder和Decoder结点的一部分。至于bias……好吧,我目前还不知道这个bias是干什么的。

(不,我现在意识到了,之前的描述中为了简便起见忽略了所有bias项,但显然这些项还是得有的。)

encoder

encoder:整个Transformer的encoder

图中encoder的输入有两个:一个是dropoutadding_timing_signal -> dropout),一个是attention_biasSequenceMask -> attention_bias)。我觉得数据应该是通过dropout输入的(因为按照Transformer的论文,数据是加了time signal之后输入到encoder的……),不过我现在只发现数据从batch_examples输入到SequenceMask了。

以及几乎所有结点都有一个叫create_train_op的输入,这个结点定义在optimize.py里,我猜测它是TensorFlow生成的后向图,用于对参数进行更新。

encoder内部的6个layer

encoder的内部是这样的:6个layer连在一起,这一点倒是很清楚。

encoder中一个layer的结构:attention+前馈网络

每一层内部都是self_attention加上feed_forward

attention的内部结构:multi-attention+layer-normalization

self_attention这个部分中,主要就是multihead_attention进行dropout和layer-normalization。

multi-attention的内部结构:split+merge

在这个结点中,输入似乎首先被用于计算出q、k、v三个部分,然后再在q、k、v的计算中各自进行多个操作(所以只有3个split_heads结点……?),最后再通过combine_heads合并在一起。

decoder

decoder

decoder的输入包括翻译后的数据(如果有的话)、bias和encoder的输出。

decoder内部由6层组成

decoder内部也由6个layer组成,其中每一个layer的输入除了前一个layer的输入外,还有数据、bias和encoder的输出(大概是这样的)。

decoder的一层:self-attention + encoder-decoder attention + 前馈网络

每个layer内部由self_attentionencdec_attentionfeed_forward三部分组成,其中接收encoder输出的是encdec_attentionself_attentionencdec_attention的结构与encoder的self_attention结构基本相同,但是在q、k、v的计算上有一些差异。以及feed_forward中含有一个ffn_layer

softmax

linear + softmax:输出概率

decoder的输出通过softmax层得到概率。(大概是这样的)

Relevance

UserManual中提供了计算每个源句和翻译出来的目标句之间的relevance矩阵的工具。不过鉴于我这个结果的翻译质量,就先不去尝试了……


  1. StackOverflow - How can I remove unused packages from virtualenv?

  2. StackOverflow - How do you set your pythonpath in an already-created virtualenv?

  3. Moses - Preparing Training Data

  4. Moses - Truecaser

  5. PLM's blog - subword-units


 评论