sonithoiningombam commited on
Commit
376f14d
·
verified ·
1 Parent(s): 37c6b04

Add files using upload-large-folder tool

Browse files
data/fairseq/scripts/__init__.py ADDED
File without changes
data/fairseq/scripts/average_checkpoints.py ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) Facebook, Inc. and its affiliates.
3
+ #
4
+ # This source code is licensed under the MIT license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ import argparse
8
+ import collections
9
+ import os
10
+ import re
11
+
12
+ import torch
13
+
14
+ from fairseq.file_io import PathManager
15
+
16
+
17
+ def average_checkpoints(inputs):
18
+ """Loads checkpoints from inputs and returns a model with averaged weights.
19
+
20
+ Args:
21
+ inputs: An iterable of string paths of checkpoints to load from.
22
+
23
+ Returns:
24
+ A dict of string keys mapping to various values. The 'model' key
25
+ from the returned dict should correspond to an OrderedDict mapping
26
+ string parameter names to torch Tensors.
27
+ """
28
+ params_dict = collections.OrderedDict()
29
+ params_keys = None
30
+ new_state = None
31
+ num_models = len(inputs)
32
+
33
+ for fpath in inputs:
34
+ with PathManager.open(fpath, "rb") as f:
35
+ state = torch.load(
36
+ f,
37
+ map_location=(
38
+ lambda s, _: torch.serialization.default_restore_location(s, "cpu")
39
+ ),
40
+ )
41
+ # Copies over the settings from the first checkpoint
42
+ if new_state is None:
43
+ new_state = state
44
+
45
+ model_params = state["model"]
46
+
47
+ model_params_keys = list(model_params.keys())
48
+ if params_keys is None:
49
+ params_keys = model_params_keys
50
+ elif params_keys != model_params_keys:
51
+ raise KeyError(
52
+ "For checkpoint {}, expected list of params: {}, "
53
+ "but found: {}".format(f, params_keys, model_params_keys)
54
+ )
55
+
56
+ for k in params_keys:
57
+ p = model_params[k]
58
+ if isinstance(p, torch.HalfTensor):
59
+ p = p.float()
60
+ if k not in params_dict:
61
+ params_dict[k] = p.clone()
62
+ # NOTE: clone() is needed in case of p is a shared parameter
63
+ else:
64
+ params_dict[k] += p
65
+
66
+ averaged_params = collections.OrderedDict()
67
+ for k, v in params_dict.items():
68
+ averaged_params[k] = v
69
+ if averaged_params[k].is_floating_point():
70
+ averaged_params[k].div_(num_models)
71
+ else:
72
+ averaged_params[k] //= num_models
73
+ new_state["model"] = averaged_params
74
+ return new_state
75
+
76
+
77
+ def last_n_checkpoints(paths, n, update_based, upper_bound=None):
78
+ assert len(paths) == 1
79
+ path = paths[0]
80
+ if update_based:
81
+ pt_regexp = re.compile(r"checkpoint_\d+_(\d+)\.pt")
82
+ else:
83
+ pt_regexp = re.compile(r"checkpoint(\d+)\.pt")
84
+ files = PathManager.ls(path)
85
+
86
+ entries = []
87
+ for f in files:
88
+ m = pt_regexp.fullmatch(f)
89
+ if m is not None:
90
+ sort_key = int(m.group(1))
91
+ if upper_bound is None or sort_key <= upper_bound:
92
+ entries.append((sort_key, m.group(0)))
93
+ if len(entries) < n:
94
+ raise Exception(
95
+ "Found {} checkpoint files but need at least {}", len(entries), n
96
+ )
97
+ return [os.path.join(path, x[1]) for x in sorted(entries, reverse=True)[:n]]
98
+
99
+
100
+ def main():
101
+ parser = argparse.ArgumentParser(
102
+ description="Tool to average the params of input checkpoints to "
103
+ "produce a new checkpoint",
104
+ )
105
+ # fmt: off
106
+ parser.add_argument('--inputs', required=True, nargs='+',
107
+ help='Input checkpoint file paths.')
108
+ parser.add_argument('--output', required=True, metavar='FILE',
109
+ help='Write the new checkpoint containing the averaged weights to this path.')
110
+ num_group = parser.add_mutually_exclusive_group()
111
+ num_group.add_argument('--num-epoch-checkpoints', type=int,
112
+ help='if set, will try to find checkpoints with names checkpoint_xx.pt in the '
113
+ 'path specified by input, and average last this many of them.')
114
+ num_group.add_argument('--num-update-checkpoints', type=int,
115
+ help='if set, will try to find checkpoints with names checkpoint_ee_xx.pt in the path specified by'
116
+ ' input, and average last this many of them.')
117
+ num_group.add_argument('--num-best-checkpoints', type=int, default=0,
118
+ help='if set, will try to find checkpoints with names checkpoint_best_ee_xx.pt in the path specified by'
119
+ ' input, and average last this many of them.')
120
+ parser.add_argument('--checkpoint-upper-bound', type=int,
121
+ help='when using --num-epoch-checkpoints, this will set an upper bound on which epoch to use, '
122
+ 'when using --num-update-checkpoints, this will set an upper bound on which update to use'
123
+ 'e.g., with --num-epoch-checkpoints=10 --checkpoint-upper-bound=50, checkpoints 41-50 would be'
124
+ ' averaged.'
125
+ 'e.g., with --num-update-checkpoints=10 --checkpoint-upper-bound=50000, checkpoints 40500-50000 would'
126
+ ' be averaged assuming --save-interval-updates 500'
127
+ )
128
+ # fmt: on
129
+ args = parser.parse_args()
130
+ print(args)
131
+
132
+ num = None
133
+ is_update_based = False
134
+ if args.num_update_checkpoints is not None:
135
+ num = args.num_update_checkpoints
136
+ is_update_based = True
137
+ elif args.num_epoch_checkpoints is not None:
138
+ num = args.num_epoch_checkpoints
139
+
140
+ assert args.checkpoint_upper_bound is None or (
141
+ args.num_epoch_checkpoints is not None
142
+ or args.num_update_checkpoints is not None
143
+ ), "--checkpoint-upper-bound requires --num-epoch-checkpoints or --num-update-checkpoints"
144
+ assert (
145
+ args.num_epoch_checkpoints is None or args.num_update_checkpoints is None
146
+ ), "Cannot combine --num-epoch-checkpoints and --num-update-checkpoints"
147
+
148
+ if num is not None:
149
+ args.inputs = last_n_checkpoints(
150
+ args.inputs,
151
+ num,
152
+ is_update_based,
153
+ upper_bound=args.checkpoint_upper_bound,
154
+ )
155
+ print("averaging checkpoints: ", args.inputs)
156
+
157
+ if args.num_best_checkpoints > 0:
158
+ args.inputs = list(
159
+ sorted(
160
+ args.inputs,
161
+ key=lambda x: float(
162
+ os.path.basename(x).split("_")[-1].replace(".pt", "")
163
+ ),
164
+ )
165
+ )
166
+ args.inputs = args.inputs[: args.num_best_checkpoints]
167
+ for path in args.inputs:
168
+ print(os.path.basename(path))
169
+ new_state = average_checkpoints(args.inputs)
170
+ with PathManager.open(args.output, "wb") as f:
171
+ torch.save(new_state, f)
172
+ print("Finished writing averaged checkpoint to {}".format(args.output))
173
+
174
+
175
+ if __name__ == "__main__":
176
+ main()
data/fairseq/scripts/build_sym_alignment.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Facebook, Inc. and its affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+ """
6
+ Use this script in order to build symmetric alignments for your translation
7
+ dataset.
8
+ This script depends on fast_align and mosesdecoder tools. You will need to
9
+ build those before running the script.
10
+ fast_align:
11
+ github: http://github.com/clab/fast_align
12
+ instructions: follow the instructions in README.md
13
+ mosesdecoder:
14
+ github: http://github.com/moses-smt/mosesdecoder
15
+ instructions: http://www.statmt.org/moses/?n=Development.GetStarted
16
+ The script produces the following files under --output_dir:
17
+ text.joined - concatenation of lines from the source_file and the
18
+ target_file.
19
+ align.forward - forward pass of fast_align.
20
+ align.backward - backward pass of fast_align.
21
+ aligned.sym_heuristic - symmetrized alignment.
22
+ """
23
+
24
+ import argparse
25
+ import os
26
+ from itertools import zip_longest
27
+
28
+
29
+ def main():
30
+ parser = argparse.ArgumentParser(description="symmetric alignment builer")
31
+ # fmt: off
32
+ parser.add_argument('--fast_align_dir',
33
+ help='path to fast_align build directory')
34
+ parser.add_argument('--mosesdecoder_dir',
35
+ help='path to mosesdecoder root directory')
36
+ parser.add_argument('--sym_heuristic',
37
+ help='heuristic to use for symmetrization',
38
+ default='grow-diag-final-and')
39
+ parser.add_argument('--source_file',
40
+ help='path to a file with sentences '
41
+ 'in the source language')
42
+ parser.add_argument('--target_file',
43
+ help='path to a file with sentences '
44
+ 'in the target language')
45
+ parser.add_argument('--output_dir',
46
+ help='output directory')
47
+ # fmt: on
48
+ args = parser.parse_args()
49
+
50
+ fast_align_bin = os.path.join(args.fast_align_dir, "fast_align")
51
+ symal_bin = os.path.join(args.mosesdecoder_dir, "bin", "symal")
52
+ sym_fast_align_bin = os.path.join(
53
+ args.mosesdecoder_dir, "scripts", "ems", "support", "symmetrize-fast-align.perl"
54
+ )
55
+
56
+ # create joined file
57
+ joined_file = os.path.join(args.output_dir, "text.joined")
58
+ with open(args.source_file, "r", encoding="utf-8") as src, open(
59
+ args.target_file, "r", encoding="utf-8"
60
+ ) as tgt:
61
+ with open(joined_file, "w", encoding="utf-8") as joined:
62
+ for s, t in zip_longest(src, tgt):
63
+ print("{} ||| {}".format(s.strip(), t.strip()), file=joined)
64
+
65
+ bwd_align_file = os.path.join(args.output_dir, "align.backward")
66
+
67
+ # run forward alignment
68
+ fwd_align_file = os.path.join(args.output_dir, "align.forward")
69
+ fwd_fast_align_cmd = "{FASTALIGN} -i {JOINED} -d -o -v > {FWD}".format(
70
+ FASTALIGN=fast_align_bin, JOINED=joined_file, FWD=fwd_align_file
71
+ )
72
+ assert os.system(fwd_fast_align_cmd) == 0
73
+
74
+ # run backward alignment
75
+ bwd_align_file = os.path.join(args.output_dir, "align.backward")
76
+ bwd_fast_align_cmd = "{FASTALIGN} -i {JOINED} -d -o -v -r > {BWD}".format(
77
+ FASTALIGN=fast_align_bin, JOINED=joined_file, BWD=bwd_align_file
78
+ )
79
+ assert os.system(bwd_fast_align_cmd) == 0
80
+
81
+ # run symmetrization
82
+ sym_out_file = os.path.join(args.output_dir, "aligned")
83
+ sym_cmd = "{SYMFASTALIGN} {FWD} {BWD} {SRC} {TGT} {OUT} {HEURISTIC} {SYMAL}".format(
84
+ SYMFASTALIGN=sym_fast_align_bin,
85
+ FWD=fwd_align_file,
86
+ BWD=bwd_align_file,
87
+ SRC=args.source_file,
88
+ TGT=args.target_file,
89
+ OUT=sym_out_file,
90
+ HEURISTIC=args.sym_heuristic,
91
+ SYMAL=symal_bin,
92
+ )
93
+ assert os.system(sym_cmd) == 0
94
+
95
+
96
+ if __name__ == "__main__":
97
+ main()
data/fairseq/scripts/check_installation.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ import os
3
+
4
+ cwd = Path(".").resolve()
5
+ print("running 'check_installation.py' from:", cwd)
6
+
7
+ # Old versions of numpy/torch can prevent loading the .so files
8
+ import torch
9
+
10
+ print("torch:", torch.__version__)
11
+ import numpy
12
+
13
+ print("numpy:", numpy.__version__)
14
+
15
+ import fairseq
16
+
17
+ print("Fairseq installed at:", fairseq.__file__)
18
+ import fairseq.criterions
19
+ import fairseq.dataclass.configs
20
+
21
+ import _imp
22
+
23
+ print("Should load following .so suffixes:", _imp.extension_suffixes())
24
+
25
+ so_files = list(Path(fairseq.__file__).parent.glob("*.so"))
26
+ so_files.extend(Path(fairseq.__file__).parent.glob("data/*.so"))
27
+ print("Found following .so files:")
28
+ for so_file in so_files:
29
+ print(f"- {so_file}")
30
+
31
+ from fairseq import libbleu
32
+
33
+ print("Found libbleu at", libbleu.__file__)
34
+ from fairseq.data import data_utils_fast
35
+
36
+ print("Found data_utils_fast at", data_utils_fast.__file__)
data/fairseq/scripts/compare_namespaces.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ """Helper script to compare two argparse.Namespace objects."""
3
+
4
+ from argparse import Namespace # noqa
5
+
6
+
7
+ def main():
8
+
9
+ ns1 = eval(input("Namespace 1: "))
10
+ ns2 = eval(input("Namespace 2: "))
11
+
12
+ def keys(ns):
13
+ ks = set()
14
+ for k in dir(ns):
15
+ if not k.startswith("_"):
16
+ ks.add(k)
17
+ return ks
18
+
19
+ k1 = keys(ns1)
20
+ k2 = keys(ns2)
21
+
22
+ def print_keys(ks, ns1, ns2=None):
23
+ for k in ks:
24
+ if ns2 is None:
25
+ print("{}\t{}".format(k, getattr(ns1, k, None)))
26
+ else:
27
+ print(
28
+ "{}\t{}\t{}".format(k, getattr(ns1, k, None), getattr(ns2, k, None))
29
+ )
30
+
31
+ print("Keys unique to namespace 1:")
32
+ print_keys(k1 - k2, ns1)
33
+ print()
34
+
35
+ print("Keys unique to namespace 2:")
36
+ print_keys(k2 - k1, ns2)
37
+ print()
38
+
39
+ print("Overlapping keys with different values:")
40
+ ks = [k for k in k1 & k2 if getattr(ns1, k, "None") != getattr(ns2, k, "None")]
41
+ print_keys(ks, ns1, ns2)
42
+ print()
43
+
44
+
45
+ if __name__ == "__main__":
46
+ main()
data/fairseq/scripts/compound_split_bleu.sh ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ if [ $# -ne 1 ]; then
4
+ echo "usage: $0 GENERATE_PY_OUTPUT"
5
+ exit 1
6
+ fi
7
+
8
+ GEN=$1
9
+
10
+ SYS=$GEN.sys
11
+ REF=$GEN.ref
12
+
13
+ if [ $(tail -n 1 $GEN | grep BLEU | wc -l) -ne 1 ]; then
14
+ echo "not done generating"
15
+ exit
16
+ fi
17
+
18
+ grep ^H $GEN | awk -F '\t' '{print $NF}' | perl -ple 's{(\S)-(\S)}{$1 ##AT##-##AT## $2}g' > $SYS
19
+ grep ^T $GEN | cut -f2- | perl -ple 's{(\S)-(\S)}{$1 ##AT##-##AT## $2}g' > $REF
20
+ fairseq-score --sys $SYS --ref $REF
data/fairseq/scripts/constraints/extract.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ #
3
+ # Copyright (c) Facebook, Inc. and its affiliates.
4
+ #
5
+ # This source code is licensed under the MIT license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+
8
+ """Extracts random constraints from reference files."""
9
+
10
+ import argparse
11
+ import random
12
+ import sys
13
+
14
+
15
+ def get_phrase(words, index, length):
16
+ assert index < len(words) - length + 1
17
+ phr = " ".join(words[index : index + length])
18
+ for i in range(index, index + length):
19
+ words.pop(index)
20
+ return phr
21
+
22
+
23
+ def main(args):
24
+
25
+ if args.seed:
26
+ random.seed(args.seed)
27
+
28
+ for line in sys.stdin:
29
+ constraints = []
30
+
31
+ def add_constraint(constraint):
32
+ constraints.append(constraint)
33
+
34
+ source = line.rstrip()
35
+ if "\t" in line:
36
+ source, target = line.split("\t")
37
+ if args.add_sos:
38
+ target = f"<s> {target}"
39
+ if args.add_eos:
40
+ target = f"{target} </s>"
41
+
42
+ if len(target.split()) >= args.len:
43
+ words = [target]
44
+
45
+ num = args.number
46
+
47
+ choices = {}
48
+ for i in range(num):
49
+ if len(words) == 0:
50
+ break
51
+ segmentno = random.choice(range(len(words)))
52
+ segment = words.pop(segmentno)
53
+ tokens = segment.split()
54
+ phrase_index = random.choice(range(len(tokens)))
55
+ choice = " ".join(
56
+ tokens[phrase_index : min(len(tokens), phrase_index + args.len)]
57
+ )
58
+ for j in range(
59
+ phrase_index, min(len(tokens), phrase_index + args.len)
60
+ ):
61
+ tokens.pop(phrase_index)
62
+ if phrase_index > 0:
63
+ words.append(" ".join(tokens[0:phrase_index]))
64
+ if phrase_index + 1 < len(tokens):
65
+ words.append(" ".join(tokens[phrase_index:]))
66
+ choices[target.find(choice)] = choice
67
+
68
+ # mask out with spaces
69
+ target = target.replace(choice, " " * len(choice), 1)
70
+
71
+ for key in sorted(choices.keys()):
72
+ add_constraint(choices[key])
73
+
74
+ print(source, *constraints, sep="\t")
75
+
76
+
77
+ if __name__ == "__main__":
78
+ parser = argparse.ArgumentParser()
79
+ parser.add_argument("--number", "-n", type=int, default=1, help="number of phrases")
80
+ parser.add_argument("--len", "-l", type=int, default=1, help="phrase length")
81
+ parser.add_argument(
82
+ "--add-sos", default=False, action="store_true", help="add <s> token"
83
+ )
84
+ parser.add_argument(
85
+ "--add-eos", default=False, action="store_true", help="add </s> token"
86
+ )
87
+ parser.add_argument("--seed", "-s", default=0, type=int)
88
+ args = parser.parse_args()
89
+
90
+ main(args)
data/fairseq/scripts/convert_dictionary.lua ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- Copyright (c) Facebook, Inc. and its affiliates.
2
+ --
3
+ -- This source code is licensed under the MIT license found in the
4
+ -- LICENSE file in the root directory of this source tree.
5
+ --
6
+ -- Usage: convert_dictionary.lua <dict.th7>
7
+ require 'fairseq'
8
+ require 'torch'
9
+ require 'paths'
10
+
11
+ if #arg < 1 then
12
+ print('usage: convert_dictionary.lua <dict.th7>')
13
+ os.exit(1)
14
+ end
15
+ if not paths.filep(arg[1]) then
16
+ print('error: file does not exit: ' .. arg[1])
17
+ os.exit(1)
18
+ end
19
+
20
+ dict = torch.load(arg[1])
21
+ dst = paths.basename(arg[1]):gsub('.th7', '.txt')
22
+ assert(dst:match('.txt$'))
23
+
24
+ f = io.open(dst, 'w')
25
+ for idx, symbol in ipairs(dict.index_to_symbol) do
26
+ if idx > dict.cutoff then
27
+ break
28
+ end
29
+ f:write(symbol)
30
+ f:write(' ')
31
+ f:write(dict.index_to_freq[idx])
32
+ f:write('\n')
33
+ end
34
+ f:close()
data/fairseq/scripts/convert_model.lua ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- Copyright (c) Facebook, Inc. and its affiliates.
2
+ --
3
+ -- This source code is licensed under the MIT license found in the
4
+ -- LICENSE file in the root directory of this source tree.
5
+ --
6
+ -- Usage: convert_model.lua <model_epoch1.th7>
7
+ require 'torch'
8
+ local fairseq = require 'fairseq'
9
+
10
+ model = torch.load(arg[1])
11
+
12
+ function find_weight_norm(container, module)
13
+ for _, wn in ipairs(container:listModules()) do
14
+ if torch.type(wn) == 'nn.WeightNorm' and wn.modules[1] == module then
15
+ return wn
16
+ end
17
+ end
18
+ end
19
+
20
+ function push_state(dict, key, module)
21
+ if torch.type(module) == 'nn.Linear' then
22
+ local wn = find_weight_norm(model.module, module)
23
+ assert(wn)
24
+ dict[key .. '.weight_v'] = wn.v:float()
25
+ dict[key .. '.weight_g'] = wn.g:float()
26
+ elseif torch.type(module) == 'nn.TemporalConvolutionTBC' then
27
+ local wn = find_weight_norm(model.module, module)
28
+ assert(wn)
29
+ local v = wn.v:float():view(wn.viewOut):transpose(2, 3)
30
+ dict[key .. '.weight_v'] = v
31
+ dict[key .. '.weight_g'] = wn.g:float():view(module.weight:size(3), 1, 1)
32
+ else
33
+ dict[key .. '.weight'] = module.weight:float()
34
+ end
35
+ if module.bias then
36
+ dict[key .. '.bias'] = module.bias:float()
37
+ end
38
+ end
39
+
40
+ encoder_dict = {}
41
+ decoder_dict = {}
42
+ combined_dict = {}
43
+
44
+ function encoder_state(encoder)
45
+ luts = encoder:findModules('nn.LookupTable')
46
+ push_state(encoder_dict, 'embed_tokens', luts[1])
47
+ push_state(encoder_dict, 'embed_positions', luts[2])
48
+
49
+ fcs = encoder:findModules('nn.Linear')
50
+ assert(#fcs >= 2)
51
+ local nInputPlane = fcs[1].weight:size(1)
52
+ push_state(encoder_dict, 'fc1', table.remove(fcs, 1))
53
+ push_state(encoder_dict, 'fc2', table.remove(fcs, #fcs))
54
+
55
+ for i, module in ipairs(encoder:findModules('nn.TemporalConvolutionTBC')) do
56
+ push_state(encoder_dict, 'convolutions.' .. tostring(i - 1), module)
57
+ if nInputPlane ~= module.weight:size(3) / 2 then
58
+ push_state(encoder_dict, 'projections.' .. tostring(i - 1), table.remove(fcs, 1))
59
+ end
60
+ nInputPlane = module.weight:size(3) / 2
61
+ end
62
+ assert(#fcs == 0)
63
+ end
64
+
65
+ function decoder_state(decoder)
66
+ luts = decoder:findModules('nn.LookupTable')
67
+ push_state(decoder_dict, 'embed_tokens', luts[1])
68
+ push_state(decoder_dict, 'embed_positions', luts[2])
69
+
70
+ fcs = decoder:findModules('nn.Linear')
71
+ local nInputPlane = fcs[1].weight:size(1)
72
+ push_state(decoder_dict, 'fc1', table.remove(fcs, 1))
73
+ push_state(decoder_dict, 'fc2', fcs[#fcs - 1])
74
+ push_state(decoder_dict, 'fc3', fcs[#fcs])
75
+
76
+ table.remove(fcs, #fcs)
77
+ table.remove(fcs, #fcs)
78
+
79
+ for i, module in ipairs(decoder:findModules('nn.TemporalConvolutionTBC')) do
80
+ if nInputPlane ~= module.weight:size(3) / 2 then
81
+ push_state(decoder_dict, 'projections.' .. tostring(i - 1), table.remove(fcs, 1))
82
+ end
83
+ nInputPlane = module.weight:size(3) / 2
84
+
85
+ local prefix = 'attention.' .. tostring(i - 1)
86
+ push_state(decoder_dict, prefix .. '.in_projection', table.remove(fcs, 1))
87
+ push_state(decoder_dict, prefix .. '.out_projection', table.remove(fcs, 1))
88
+ push_state(decoder_dict, 'convolutions.' .. tostring(i - 1), module)
89
+ end
90
+ assert(#fcs == 0)
91
+ end
92
+
93
+
94
+ _encoder = model.module.modules[2]
95
+ _decoder = model.module.modules[3]
96
+
97
+ encoder_state(_encoder)
98
+ decoder_state(_decoder)
99
+
100
+ for k, v in pairs(encoder_dict) do
101
+ combined_dict['encoder.' .. k] = v
102
+ end
103
+ for k, v in pairs(decoder_dict) do
104
+ combined_dict['decoder.' .. k] = v
105
+ end
106
+
107
+
108
+ torch.save('state_dict.t7', combined_dict)
data/fairseq/scripts/count_docs.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) Facebook, Inc. and its affiliates.
3
+ #
4
+ # This source code is licensed under the MIT license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+ """
7
+ Count the number of documents and average number of lines and tokens per
8
+ document in a large file. Documents should be separated by a single empty line.
9
+ """
10
+
11
+ import argparse
12
+ import gzip
13
+ import sys
14
+
15
+ import numpy as np
16
+
17
+
18
+ def main():
19
+ parser = argparse.ArgumentParser()
20
+ parser.add_argument("input")
21
+ parser.add_argument("--gzip", action="store_true")
22
+ args = parser.parse_args()
23
+
24
+ def gopen():
25
+ if args.gzip:
26
+ return gzip.open(args.input, "r")
27
+ else:
28
+ return open(args.input, "r", encoding="utf-8")
29
+
30
+ num_lines = []
31
+ num_toks = []
32
+ with gopen() as h:
33
+ num_docs = 1
34
+ num_lines_in_doc = 0
35
+ num_toks_in_doc = 0
36
+ for i, line in enumerate(h):
37
+ if len(line.strip()) == 0: # empty line indicates new document
38
+ num_docs += 1
39
+ num_lines.append(num_lines_in_doc)
40
+ num_toks.append(num_toks_in_doc)
41
+ num_lines_in_doc = 0
42
+ num_toks_in_doc = 0
43
+ else:
44
+ num_lines_in_doc += 1
45
+ num_toks_in_doc += len(line.rstrip().split())
46
+ if i % 1000000 == 0:
47
+ print(i, file=sys.stderr, end="", flush=True)
48
+ elif i % 100000 == 0:
49
+ print(".", file=sys.stderr, end="", flush=True)
50
+ print(file=sys.stderr, flush=True)
51
+
52
+ print("found {} docs".format(num_docs))
53
+ print("average num lines per doc: {}".format(np.mean(num_lines)))
54
+ print("average num toks per doc: {}".format(np.mean(num_toks)))
55
+
56
+
57
+ if __name__ == "__main__":
58
+ main()
data/fairseq/scripts/read_binarized.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) Facebook, Inc. and its affiliates.
3
+ #
4
+ # This source code is licensed under the MIT license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ import argparse
8
+
9
+ from fairseq.data import Dictionary, data_utils, indexed_dataset
10
+
11
+
12
+ def get_parser():
13
+ parser = argparse.ArgumentParser(
14
+ description="writes text from binarized file to stdout"
15
+ )
16
+ # fmt: off
17
+ parser.add_argument('--dataset-impl', help='dataset implementation',
18
+ choices=indexed_dataset.get_available_dataset_impl())
19
+ parser.add_argument('--dict', metavar='FP', help='dictionary containing known words', default=None)
20
+ parser.add_argument('--input', metavar='FP', required=True, help='binarized file to read')
21
+ # fmt: on
22
+
23
+ return parser
24
+
25
+
26
+ def main():
27
+ parser = get_parser()
28
+ args = parser.parse_args()
29
+
30
+ dictionary = Dictionary.load(args.dict) if args.dict is not None else None
31
+ dataset = data_utils.load_indexed_dataset(
32
+ args.input,
33
+ dictionary,
34
+ dataset_impl=args.dataset_impl,
35
+ default="lazy",
36
+ )
37
+
38
+ for tensor_line in dataset:
39
+ if dictionary is None:
40
+ line = " ".join([str(int(x)) for x in tensor_line])
41
+ else:
42
+ line = dictionary.string(tensor_line)
43
+
44
+ print(line)
45
+
46
+
47
+ if __name__ == "__main__":
48
+ main()
data/fairseq/scripts/rm_pt.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) Facebook, Inc. and its affiliates.
3
+ #
4
+ # This source code is licensed under the MIT license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ import argparse
8
+ import os
9
+ import re
10
+ import shutil
11
+ import sys
12
+
13
+
14
+ pt_regexp = re.compile(r"checkpoint(\d+|_\d+_\d+|_[a-z]+)\.pt")
15
+ pt_regexp_epoch_based = re.compile(r"checkpoint(\d+)\.pt")
16
+ pt_regexp_update_based = re.compile(r"checkpoint_\d+_(\d+)\.pt")
17
+
18
+
19
+ def parse_checkpoints(files):
20
+ entries = []
21
+ for f in files:
22
+ m = pt_regexp_epoch_based.fullmatch(f)
23
+ if m is not None:
24
+ entries.append((int(m.group(1)), m.group(0)))
25
+ else:
26
+ m = pt_regexp_update_based.fullmatch(f)
27
+ if m is not None:
28
+ entries.append((int(m.group(1)), m.group(0)))
29
+ return entries
30
+
31
+
32
+ def last_n_checkpoints(files, n):
33
+ entries = parse_checkpoints(files)
34
+ return [x[1] for x in sorted(entries, reverse=True)[:n]]
35
+
36
+
37
+ def every_n_checkpoints(files, n):
38
+ entries = parse_checkpoints(files)
39
+ return [x[1] for x in sorted(sorted(entries)[::-n])]
40
+
41
+
42
+ def main():
43
+ parser = argparse.ArgumentParser(
44
+ description=(
45
+ "Recursively delete checkpoint files from `root_dir`, "
46
+ "but preserve checkpoint_best.pt and checkpoint_last.pt"
47
+ )
48
+ )
49
+ parser.add_argument("root_dirs", nargs="*")
50
+ parser.add_argument(
51
+ "--save-last", type=int, default=0, help="number of last checkpoints to save"
52
+ )
53
+ parser.add_argument(
54
+ "--save-every", type=int, default=0, help="interval of checkpoints to save"
55
+ )
56
+ parser.add_argument(
57
+ "--preserve-test",
58
+ action="store_true",
59
+ help="preserve checkpoints in dirs that start with test_ prefix (default: delete them)",
60
+ )
61
+ parser.add_argument(
62
+ "--delete-best", action="store_true", help="delete checkpoint_best.pt"
63
+ )
64
+ parser.add_argument(
65
+ "--delete-last", action="store_true", help="delete checkpoint_last.pt"
66
+ )
67
+ parser.add_argument(
68
+ "--no-dereference", action="store_true", help="don't dereference symlinks"
69
+ )
70
+ args = parser.parse_args()
71
+
72
+ files_to_desymlink = []
73
+ files_to_preserve = []
74
+ files_to_delete = []
75
+ for root_dir in args.root_dirs:
76
+ for root, _subdirs, files in os.walk(root_dir):
77
+ if args.save_last > 0:
78
+ to_save = last_n_checkpoints(files, args.save_last)
79
+ else:
80
+ to_save = []
81
+ if args.save_every > 0:
82
+ to_save += every_n_checkpoints(files, args.save_every)
83
+ for file in files:
84
+ if not pt_regexp.fullmatch(file):
85
+ continue
86
+ full_path = os.path.join(root, file)
87
+ if (
88
+ not os.path.basename(root).startswith("test_") or args.preserve_test
89
+ ) and (
90
+ (file == "checkpoint_last.pt" and not args.delete_last)
91
+ or (file == "checkpoint_best.pt" and not args.delete_best)
92
+ or file in to_save
93
+ ):
94
+ if os.path.islink(full_path) and not args.no_dereference:
95
+ files_to_desymlink.append(full_path)
96
+ else:
97
+ files_to_preserve.append(full_path)
98
+ else:
99
+ files_to_delete.append(full_path)
100
+
101
+ if len(files_to_desymlink) == 0 and len(files_to_delete) == 0:
102
+ print("Nothing to do.")
103
+ sys.exit(0)
104
+
105
+ files_to_desymlink = sorted(files_to_desymlink)
106
+ files_to_preserve = sorted(files_to_preserve)
107
+ files_to_delete = sorted(files_to_delete)
108
+
109
+ print("Operations to perform (in order):")
110
+ if len(files_to_desymlink) > 0:
111
+ for file in files_to_desymlink:
112
+ print(" - preserve (and dereference symlink): " + file)
113
+ if len(files_to_preserve) > 0:
114
+ for file in files_to_preserve:
115
+ print(" - preserve: " + file)
116
+ if len(files_to_delete) > 0:
117
+ for file in files_to_delete:
118
+ print(" - delete: " + file)
119
+ while True:
120
+ resp = input("Continue? (Y/N): ")
121
+ if resp.strip().lower() == "y":
122
+ break
123
+ elif resp.strip().lower() == "n":
124
+ sys.exit(0)
125
+
126
+ print("Executing...")
127
+ if len(files_to_desymlink) > 0:
128
+ for file in files_to_desymlink:
129
+ realpath = os.path.realpath(file)
130
+ print("rm " + file)
131
+ os.remove(file)
132
+ print("cp {} {}".format(realpath, file))
133
+ shutil.copyfile(realpath, file)
134
+ if len(files_to_delete) > 0:
135
+ for file in files_to_delete:
136
+ print("rm " + file)
137
+ os.remove(file)
138
+
139
+
140
+ if __name__ == "__main__":
141
+ main()
data/fairseq/scripts/sacrebleu.sh ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ if [ $# -ne 4 ]; then
4
+ echo "usage: $0 TESTSET SRCLANG TGTLANG GEN"
5
+ exit 1
6
+ fi
7
+
8
+ TESTSET=$1
9
+ SRCLANG=$2
10
+ TGTLANG=$3
11
+
12
+ GEN=$4
13
+
14
+ if ! command -v sacremoses &> /dev/null
15
+ then
16
+ echo "sacremoses could not be found, please install with: pip install sacremoses"
17
+ exit
18
+ fi
19
+
20
+ grep ^H $GEN \
21
+ | sed 's/^H\-//' \
22
+ | sort -n -k 1 \
23
+ | cut -f 3 \
24
+ | sacremoses detokenize \
25
+ > $GEN.sorted.detok
26
+
27
+ sacrebleu --test-set $TESTSET --language-pair "${SRCLANG}-${TGTLANG}" < $GEN.sorted.detok
data/fairseq/scripts/shard_docs.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) Facebook, Inc. and its affiliates.
3
+ #
4
+ # This source code is licensed under the MIT license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+ """
7
+ Split a large file into shards while respecting document boundaries. Documents
8
+ should be separated by a single empty line.
9
+ """
10
+
11
+ import argparse
12
+ import contextlib
13
+
14
+
15
+ def main():
16
+ parser = argparse.ArgumentParser()
17
+ parser.add_argument("input")
18
+ parser.add_argument("--num-shards", type=int)
19
+ args = parser.parse_args()
20
+
21
+ assert args.num_shards is not None and args.num_shards > 1
22
+
23
+ with open(args.input, "r", encoding="utf-8") as h:
24
+ with contextlib.ExitStack() as stack:
25
+ outputs = [
26
+ stack.enter_context(
27
+ open(args.input + ".shard" + str(i), "w", encoding="utf-8")
28
+ )
29
+ for i in range(args.num_shards)
30
+ ]
31
+
32
+ doc = []
33
+ first_doc = [True] * args.num_shards
34
+
35
+ def output_doc(i):
36
+ if not first_doc[i]:
37
+ outputs[i].write("\n")
38
+ first_doc[i] = False
39
+ for line in doc:
40
+ outputs[i].write(line)
41
+ doc.clear()
42
+
43
+ num_docs = 0
44
+ for line in h:
45
+ if line.strip() == "": # empty line indicates new document
46
+ output_doc(num_docs % args.num_shards)
47
+ num_docs += 1
48
+ else:
49
+ doc.append(line)
50
+ output_doc(num_docs % args.num_shards)
51
+
52
+
53
+ if __name__ == "__main__":
54
+ main()
data/fairseq/scripts/split_train_valid_docs.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) Facebook, Inc. and its affiliates.
3
+ #
4
+ # This source code is licensed under the MIT license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+ """
7
+ Split a large file into a train and valid set while respecting document
8
+ boundaries. Documents should be separated by a single empty line.
9
+ """
10
+
11
+ import argparse
12
+ import random
13
+ import sys
14
+
15
+
16
+ def main():
17
+ parser = argparse.ArgumentParser()
18
+ parser.add_argument("input")
19
+ parser.add_argument("sample_output", help="train output file")
20
+ parser.add_argument("remainder_output", help="valid output file")
21
+ parser.add_argument("-k", type=int, help="remainder size")
22
+ parser.add_argument(
23
+ "--lines", action="store_true", help="split lines instead of docs"
24
+ )
25
+ args = parser.parse_args()
26
+
27
+ assert args.k is not None
28
+
29
+ sample = []
30
+ remainder = []
31
+ num_docs = [0]
32
+
33
+ def update_sample(doc):
34
+ if len(sample) < args.k:
35
+ sample.append(doc.copy())
36
+ else:
37
+ i = num_docs[0]
38
+ j = random.randrange(i + 1)
39
+ if j < args.k:
40
+ remainder.append(sample[j])
41
+ sample[j] = doc.copy()
42
+ else:
43
+ remainder.append(doc.copy())
44
+ num_docs[0] += 1
45
+ doc.clear()
46
+
47
+ with open(args.input, "r", encoding="utf-8") as h:
48
+ doc = []
49
+ for i, line in enumerate(h):
50
+ if line.strip() == "": # empty line indicates new document
51
+ update_sample(doc)
52
+ else:
53
+ doc.append(line)
54
+ if args.lines:
55
+ update_sample(doc)
56
+ if i % 1000000 == 0:
57
+ print(i, file=sys.stderr, end="", flush=True)
58
+ elif i % 100000 == 0:
59
+ print(".", file=sys.stderr, end="", flush=True)
60
+ if len(doc) > 0:
61
+ update_sample(doc)
62
+ print(file=sys.stderr, flush=True)
63
+
64
+ assert len(sample) == args.k
65
+
66
+ with open(args.sample_output, "w", encoding="utf-8") as out:
67
+ first = True
68
+ for doc in sample:
69
+ if not first and not args.lines:
70
+ out.write("\n")
71
+ first = False
72
+ for line in doc:
73
+ out.write(line)
74
+
75
+ with open(args.remainder_output, "w", encoding="utf-8") as out:
76
+ first = True
77
+ for doc in remainder:
78
+ if not first and not args.lines:
79
+ out.write("\n")
80
+ first = False
81
+ for line in doc:
82
+ out.write(line)
83
+
84
+
85
+ if __name__ == "__main__":
86
+ main()
data/fairseq/scripts/spm_decode.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # Copyright (c) Facebook, Inc. and its affiliates.
3
+ # All rights reserved.
4
+ #
5
+ # This source code is licensed under the license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+
8
+ from __future__ import absolute_import, division, print_function, unicode_literals
9
+
10
+ import argparse
11
+
12
+ import sentencepiece as spm
13
+
14
+
15
+ def main():
16
+ parser = argparse.ArgumentParser()
17
+ parser.add_argument(
18
+ "--model", required=True, help="sentencepiece model to use for decoding"
19
+ )
20
+ parser.add_argument("--input", required=True, help="input file to decode")
21
+ parser.add_argument("--input_format", choices=["piece", "id"], default="piece")
22
+ args = parser.parse_args()
23
+
24
+ sp = spm.SentencePieceProcessor()
25
+ sp.Load(args.model)
26
+
27
+ if args.input_format == "piece":
28
+
29
+ def decode(input):
30
+ return "".join(sp.DecodePieces(input))
31
+
32
+ elif args.input_format == "id":
33
+
34
+ def decode(input):
35
+ return "".join(sp.DecodeIds(input))
36
+
37
+ else:
38
+ raise NotImplementedError
39
+
40
+ def tok2int(tok):
41
+ # remap reference-side <unk> (represented as <<unk>>) to 0
42
+ return int(tok) if tok != "<<unk>>" else 0
43
+
44
+ with open(args.input, "r", encoding="utf-8") as h:
45
+ for line in h:
46
+ if args.input_format == "id":
47
+ print(decode(list(map(tok2int, line.rstrip().split()))))
48
+ elif args.input_format == "piece":
49
+ print(decode(line.rstrip().split()))
50
+
51
+
52
+ if __name__ == "__main__":
53
+ main()
data/fairseq/scripts/spm_encode.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # Copyright (c) Facebook, Inc. and its affiliates.
3
+ # All rights reserved.
4
+ #
5
+ # This source code is licensed under the license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+
8
+ from __future__ import absolute_import, division, print_function, unicode_literals
9
+
10
+ import argparse
11
+ import contextlib
12
+ import sys
13
+
14
+ import sentencepiece as spm
15
+
16
+
17
+ def main():
18
+ parser = argparse.ArgumentParser()
19
+ parser.add_argument(
20
+ "--model", required=True, help="sentencepiece model to use for encoding"
21
+ )
22
+ parser.add_argument(
23
+ "--inputs", nargs="+", default=["-"], help="input files to filter/encode"
24
+ )
25
+ parser.add_argument(
26
+ "--outputs", nargs="+", default=["-"], help="path to save encoded outputs"
27
+ )
28
+ parser.add_argument("--output_format", choices=["piece", "id"], default="piece")
29
+ parser.add_argument(
30
+ "--min-len",
31
+ type=int,
32
+ metavar="N",
33
+ help="filter sentence pairs with fewer than N tokens",
34
+ )
35
+ parser.add_argument(
36
+ "--max-len",
37
+ type=int,
38
+ metavar="N",
39
+ help="filter sentence pairs with more than N tokens",
40
+ )
41
+ args = parser.parse_args()
42
+
43
+ assert len(args.inputs) == len(
44
+ args.outputs
45
+ ), "number of input and output paths should match"
46
+
47
+ sp = spm.SentencePieceProcessor()
48
+ sp.Load(args.model)
49
+
50
+ if args.output_format == "piece":
51
+
52
+ def encode(input):
53
+ return sp.EncodeAsPieces(input)
54
+
55
+ elif args.output_format == "id":
56
+
57
+ def encode(input):
58
+ return list(map(str, sp.EncodeAsIds(input)))
59
+
60
+ else:
61
+ raise NotImplementedError
62
+
63
+ if args.min_len is not None or args.max_len is not None:
64
+
65
+ def valid(line):
66
+ return (args.min_len is None or len(line) >= args.min_len) and (
67
+ args.max_len is None or len(line) <= args.max_len
68
+ )
69
+
70
+ else:
71
+
72
+ def valid(lines):
73
+ return True
74
+
75
+ with contextlib.ExitStack() as stack:
76
+ inputs = [
77
+ stack.enter_context(open(input, "r", encoding="utf-8"))
78
+ if input != "-"
79
+ else sys.stdin
80
+ for input in args.inputs
81
+ ]
82
+ outputs = [
83
+ stack.enter_context(open(output, "w", encoding="utf-8"))
84
+ if output != "-"
85
+ else sys.stdout
86
+ for output in args.outputs
87
+ ]
88
+
89
+ stats = {
90
+ "num_empty": 0,
91
+ "num_filtered": 0,
92
+ }
93
+
94
+ def encode_line(line):
95
+ line = line.strip()
96
+ if len(line) > 0:
97
+ line = encode(line)
98
+ if valid(line):
99
+ return line
100
+ else:
101
+ stats["num_filtered"] += 1
102
+ else:
103
+ stats["num_empty"] += 1
104
+ return None
105
+
106
+ for i, lines in enumerate(zip(*inputs), start=1):
107
+ enc_lines = list(map(encode_line, lines))
108
+ if not any(enc_line is None for enc_line in enc_lines):
109
+ for enc_line, output_h in zip(enc_lines, outputs):
110
+ print(" ".join(enc_line), file=output_h)
111
+ if i % 10000 == 0:
112
+ print("processed {} lines".format(i), file=sys.stderr)
113
+
114
+ print("skipped {} empty lines".format(stats["num_empty"]), file=sys.stderr)
115
+ print("filtered {} lines".format(stats["num_filtered"]), file=sys.stderr)
116
+
117
+
118
+ if __name__ == "__main__":
119
+ main()
data/fairseq/scripts/spm_train.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # Copyright (c) Facebook, Inc. and its affiliates.
3
+ # All rights reserved.
4
+ #
5
+ # This source code is licensed under the license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+
8
+ from __future__ import absolute_import, division, print_function, unicode_literals
9
+
10
+ import sys
11
+
12
+ import sentencepiece as spm
13
+
14
+
15
+ if __name__ == "__main__":
16
+ spm.SentencePieceTrainer.Train(" ".join(sys.argv[1:]))
data/fairseq/scripts/test_fsdp.sh ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ rm -rf fsdp_dummy
3
+ mkdir -p fsdp_dummy
4
+ CUDA_VISIBLE_DEVICES=0,1,2,3 fairseq-train /private/home/sshleifer/data-bin/stories_mmap \
5
+ --ddp-backend fully_sharded --fp16 --fp16-init-scale 4 \
6
+ --cpu-offload --checkpoint-activations \
7
+ --task language_modeling --tokens-per-sample 256 --batch-size 8 \
8
+ --arch transformer_lm_gpt2_tiny \
9
+ --optimizer cpu_adam --adam-betas "(0.9,0.98)" \
10
+ --lr 0.0001 --lr-scheduler polynomial_decay --warmup-updates 5 --total-num-update 10 \
11
+ --max-update 5 --log-format json --log-interval 1 \
12
+ --save-interval-updates 5 --save-dir fsdp_dummy --disable-validation \
13
+ --restore-file x.pt "$@"
14
+
15
+ # Now we try to load the checkpoint
16
+ CUDA_VISIBLE_DEVICES=0,1 fairseq-train /private/home/sshleifer/data-bin/stories_mmap \
17
+ --ddp-backend fully_sharded --fp16 --fp16-init-scale 4 \
18
+ --cpu-offload --checkpoint-activations \
19
+ --task language_modeling --tokens-per-sample 256 --batch-size 8 \
20
+ --arch transformer_lm_gpt2_tiny \
21
+ --optimizer cpu_adam --adam-betas "(0.9,0.98)" \
22
+ --lr 0.0001 --lr-scheduler polynomial_decay --warmup-updates 5 --total-num-update 10 \
23
+ --max-update 2 --log-format json --log-interval 1 \
24
+ --save-interval-updates 2 --save-dir fsdp_dummy
data/fairseq/setup.py ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) Facebook, Inc. and its affiliates.
3
+ #
4
+ # This source code is licensed under the MIT license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ import os
8
+ import subprocess
9
+ import sys
10
+
11
+ from setuptools import Extension, find_packages, setup
12
+ from torch.utils import cpp_extension
13
+
14
+ if sys.version_info < (3, 6):
15
+ sys.exit("Sorry, Python >= 3.6 is required for fairseq.")
16
+
17
+
18
+ def write_version_py():
19
+ with open(os.path.join("fairseq", "version.txt")) as f:
20
+ version = f.read().strip()
21
+
22
+ # write version info to fairseq/version.py
23
+ with open(os.path.join("fairseq", "version.py"), "w") as f:
24
+ f.write('__version__ = "{}"\n'.format(version))
25
+ return version
26
+
27
+
28
+ version = write_version_py()
29
+
30
+
31
+ with open("README.md") as f:
32
+ readme = f.read()
33
+
34
+
35
+ if sys.platform == "darwin":
36
+ extra_compile_args = ["-stdlib=libc++", "-O3"]
37
+ else:
38
+ extra_compile_args = ["-std=c++11", "-O3"]
39
+
40
+
41
+ class NumpyExtension(Extension):
42
+ """Source: https://stackoverflow.com/a/54128391"""
43
+
44
+ def __init__(self, *args, **kwargs):
45
+ self.__include_dirs = []
46
+ super().__init__(*args, **kwargs)
47
+
48
+ @property
49
+ def include_dirs(self):
50
+ import numpy
51
+
52
+ return self.__include_dirs + [numpy.get_include()]
53
+
54
+ @include_dirs.setter
55
+ def include_dirs(self, dirs):
56
+ self.__include_dirs = dirs
57
+
58
+
59
+ extensions = [
60
+ Extension(
61
+ "fairseq.libbleu",
62
+ sources=[
63
+ "fairseq/clib/libbleu/libbleu.cpp",
64
+ "fairseq/clib/libbleu/module.cpp",
65
+ ],
66
+ extra_compile_args=extra_compile_args,
67
+ ),
68
+ NumpyExtension(
69
+ "fairseq.data.data_utils_fast",
70
+ sources=["fairseq/data/data_utils_fast.pyx"],
71
+ language="c++",
72
+ extra_compile_args=extra_compile_args,
73
+ ),
74
+ NumpyExtension(
75
+ "fairseq.data.token_block_utils_fast",
76
+ sources=["fairseq/data/token_block_utils_fast.pyx"],
77
+ language="c++",
78
+ extra_compile_args=extra_compile_args,
79
+ ),
80
+ ]
81
+
82
+
83
+ extensions.extend(
84
+ [
85
+ cpp_extension.CppExtension(
86
+ "fairseq.libbase",
87
+ sources=[
88
+ "fairseq/clib/libbase/balanced_assignment.cpp",
89
+ ],
90
+ ),
91
+ cpp_extension.CppExtension(
92
+ "fairseq.libnat",
93
+ sources=[
94
+ "fairseq/clib/libnat/edit_dist.cpp",
95
+ ],
96
+ ),
97
+ cpp_extension.CppExtension(
98
+ "alignment_train_cpu_binding",
99
+ sources=[
100
+ "examples/operators/alignment_train_cpu.cpp",
101
+ ],
102
+ ),
103
+ ]
104
+ )
105
+ if "CUDA_HOME" in os.environ:
106
+ extensions.extend(
107
+ [
108
+ cpp_extension.CppExtension(
109
+ "fairseq.libnat_cuda",
110
+ sources=[
111
+ "fairseq/clib/libnat_cuda/edit_dist.cu",
112
+ "fairseq/clib/libnat_cuda/binding.cpp",
113
+ ],
114
+ ),
115
+ cpp_extension.CppExtension(
116
+ "fairseq.ngram_repeat_block_cuda",
117
+ sources=[
118
+ "fairseq/clib/cuda/ngram_repeat_block_cuda.cpp",
119
+ "fairseq/clib/cuda/ngram_repeat_block_cuda_kernel.cu",
120
+ ],
121
+ ),
122
+ cpp_extension.CppExtension(
123
+ "alignment_train_cuda_binding",
124
+ sources=[
125
+ "examples/operators/alignment_train_kernel.cu",
126
+ "examples/operators/alignment_train_cuda.cpp",
127
+ ],
128
+ ),
129
+ ]
130
+ )
131
+
132
+ cmdclass = {"build_ext": cpp_extension.BuildExtension}
133
+
134
+ if "READTHEDOCS" in os.environ:
135
+ # don't build extensions when generating docs
136
+ extensions = []
137
+ if "build_ext" in cmdclass:
138
+ del cmdclass["build_ext"]
139
+
140
+ # use CPU build of PyTorch
141
+ dependency_links = [
142
+ "https://download.pytorch.org/whl/cpu/torch-1.7.0%2Bcpu-cp36-cp36m-linux_x86_64.whl"
143
+ ]
144
+ else:
145
+ dependency_links = []
146
+
147
+
148
+ if "clean" in sys.argv[1:]:
149
+ # Source: https://bit.ly/2NLVsgE
150
+ print("deleting Cython files...")
151
+
152
+ subprocess.run(
153
+ ["rm -f fairseq/*.so fairseq/**/*.so fairseq/*.pyd fairseq/**/*.pyd"],
154
+ shell=True,
155
+ )
156
+
157
+
158
+ extra_packages = []
159
+ if os.path.exists(os.path.join("fairseq", "model_parallel", "megatron", "mpu")):
160
+ extra_packages.append("fairseq.model_parallel.megatron.mpu")
161
+
162
+
163
+ def do_setup(package_data):
164
+ setup(
165
+ name="fairseq",
166
+ version=version,
167
+ description="Facebook AI Research Sequence-to-Sequence Toolkit",
168
+ url="https://github.com/pytorch/fairseq",
169
+ classifiers=[
170
+ "Intended Audience :: Science/Research",
171
+ "License :: OSI Approved :: MIT License",
172
+ "Programming Language :: Python :: 3.6",
173
+ "Programming Language :: Python :: 3.7",
174
+ "Programming Language :: Python :: 3.8",
175
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
176
+ ],
177
+ long_description=readme,
178
+ long_description_content_type="text/markdown",
179
+ install_requires=[
180
+ "cffi",
181
+ "cython",
182
+ "hydra-core>=1.0.7,<1.1",
183
+ "omegaconf<2.1",
184
+ "numpy>=1.21.3",
185
+ "regex",
186
+ "sacrebleu>=1.4.12",
187
+ "torch>=1.13",
188
+ "tqdm",
189
+ "bitarray",
190
+ "torchaudio>=0.8.0",
191
+ "scikit-learn",
192
+ "packaging",
193
+ ],
194
+ extras_require={
195
+ "dev": ["flake8", "pytest", "black==22.3.0"],
196
+ "docs": ["sphinx", "sphinx-argparse"],
197
+ },
198
+ dependency_links=dependency_links,
199
+ packages=find_packages(
200
+ exclude=[
201
+ "examples",
202
+ "examples.*",
203
+ "scripts",
204
+ "scripts.*",
205
+ "tests",
206
+ "tests.*",
207
+ ]
208
+ )
209
+ + extra_packages,
210
+ package_data=package_data,
211
+ ext_modules=extensions,
212
+ test_suite="tests",
213
+ entry_points={
214
+ "console_scripts": [
215
+ "fairseq-eval-lm = fairseq_cli.eval_lm:cli_main",
216
+ "fairseq-generate = fairseq_cli.generate:cli_main",
217
+ "fairseq-hydra-train = fairseq_cli.hydra_train:cli_main",
218
+ "fairseq-interactive = fairseq_cli.interactive:cli_main",
219
+ "fairseq-preprocess = fairseq_cli.preprocess:cli_main",
220
+ "fairseq-score = fairseq_cli.score:cli_main",
221
+ "fairseq-train = fairseq_cli.train:cli_main",
222
+ "fairseq-validate = fairseq_cli.validate:cli_main",
223
+ ],
224
+ },
225
+ cmdclass=cmdclass,
226
+ zip_safe=False,
227
+ )
228
+
229
+
230
+ def get_files(path, relative_to="fairseq"):
231
+ all_files = []
232
+ for root, _dirs, files in os.walk(path, followlinks=True):
233
+ root = os.path.relpath(root, relative_to)
234
+ for file in files:
235
+ if file.endswith(".pyc"):
236
+ continue
237
+ all_files.append(os.path.join(root, file))
238
+ return all_files
239
+
240
+
241
+ if __name__ == "__main__":
242
+ try:
243
+ # symlink examples into fairseq package so package_data accepts them
244
+ fairseq_examples = os.path.join("fairseq", "examples")
245
+ if "build_ext" not in sys.argv[1:] and not os.path.exists(fairseq_examples):
246
+ os.symlink(os.path.join("..", "examples"), fairseq_examples)
247
+
248
+ package_data = {
249
+ "fairseq": (
250
+ get_files(fairseq_examples)
251
+ + get_files(os.path.join("fairseq", "config"))
252
+ )
253
+ }
254
+ do_setup(package_data)
255
+ finally:
256
+ if "build_ext" not in sys.argv[1:] and os.path.islink(fairseq_examples):
257
+ os.unlink(fairseq_examples)