<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Yasmin Moslem</title>
    <description>Notes on efficient NLP and speech, from pruning and distillation to routing, serving and machine translation.</description>
    <link>https://blog.yasmin.ie/</link>
    <atom:link href="https://blog.yasmin.ie/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 28 Oct 2026 22:11:55 +0000</pubDate>
    <lastBuildDate>Wed, 28 Oct 2026 22:11:55 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>CRE-Router: Cost-Aware LLM Serving</title>
        <description>&lt;p&gt;If you serve open-weight models on your own GPUs, you pay for GPU time, and that time depends on the GPU type, the request load and the response length. CRE-Router (Cluster, Route, Escalate) is a router, which decides which model in a pool answers each query, and it prices each model by the time it takes on the hardware that serves it. On three benchmarks, it comes close to the accuracy of the strong model it escalates to, at a lower cost per token.&lt;/p&gt;

&lt;p&gt;Model routing sends each coming query to the one model in a pool that best balances cost and accuracy. Cascading lets a cheaper model answer first and passes the query to a stronger one when its answer is not good enough [1]. Most methods price a model from an API price list, a token count or a recorded run time, not from the hardware that serves it.&lt;/p&gt;

&lt;div style=&quot;text-align:center;&quot;&gt;
  &lt;img src=&quot;/static/img/cre-router/system.png&quot; alt=&quot;CRE-Router system overview&quot; style=&quot;width:100%; max-width:440px;&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Stage 1 assigns each query to a cluster and routes it to the model chosen for that cluster under the cost budget. Stage 2 lets a quality estimator accept the answer or escalate the query to the strong model.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-cre-router-works&quot;&gt;How CRE-Router Works&lt;/h2&gt;

&lt;p&gt;CRE-Router combines routing and cascading in two stages.&lt;/p&gt;

&lt;p&gt;Stage 1 groups the training queries into clusters, using k-means on their embeddings. For each cluster, it scores every model by its error on that cluster and its cost, measured either as the time per output token (TPOT) or the end-to-end latency per request (E2EL). The operator sets a budget on that cost, and CRE-Router selects the most accurate routing within it. At inference, a new query is assigned to its nearest cluster and sent to that cluster’s model, so a query from a hard cluster goes straight to a strong model and does not pay for a weak answer first.&lt;/p&gt;

&lt;p&gt;Stage 2 applies where a cluster is routed to a cheaper model. A small classifier, the quality estimator (a fine-tuned ModernBERT-base), reads each answer and either accepts it or escalates the query to the strong model. It catches the errors that routing cannot predict from the query alone.&lt;/p&gt;

&lt;p&gt;Both stages are fitted from task-correctness labels, which standard benchmark evaluation already provides, so no extra annotation is needed.&lt;/p&gt;

&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;

&lt;p&gt;We evaluated CRE-Router on two telecom benchmarks, TeleMath and TeleQnA, and on AIME, with pools of two to nine open-weight models served with vLLM on one and two A100 GPUs [2]. CRE-Router is more accurate than the cheaper models in its pool and close in accuracy to the strong model it escalates to, at a lower cost per token. Given the same cost per token, it is more than 12 points more accurate than FrugalGPT [3] on TeleMath, and significantly more accurate on TeleQnA.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/img/cre-router/telemath_pareto.png&quot; alt=&quot;CRE-Router on the Pareto frontier&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Accuracy against cost on TeleMath on one A100, per output token (left) and per request (right, log scale). Higher and further left is better; the line joins the systems that no other system beats on both. CRE-T20 is CRE-Router fitted under a TPOT budget of 20 ms. CRE-Router lies on the frontier under both cost terms.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;three-findings-about-cost&quot;&gt;Three Findings About Cost&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cost term.&lt;/strong&gt; The cost term decides which models serve the workload. TPOT does not see how long an answer is, so a TPOT budget admits models that reason at length. On TeleMath, a TPOT budget sends two of the four clusters to Qwen3-30B with reasoning, while an E2EL budget sends them to Gemma4-26B without reasoning, at about the same cost per token and a fraction of the wait per request.&lt;/p&gt;

&lt;div style=&quot;text-align:center;&quot;&gt;
  &lt;img src=&quot;/static/img/cre-router/served_wait.png&quot; alt=&quot;Time per request by cost term&quot; style=&quot;width:100%; max-width:560px;&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Every path a TeleMath request can take through CRE-Router, with the share of requests that take it and their mean E2EL. Under the TPOT budget, over 70% of requests go to reasoning models and wait more than three minutes on average; under the E2EL budget, no path averages more than 40 seconds.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-cluster cost.&lt;/strong&gt; A model can be cheap on one kind of query and expensive on another. Pricing each model per cluster, rather than with one cost for the whole workload, shortens the time per request by 20 to 22% on TeleMath, at comparable accuracy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardware.&lt;/strong&gt; A second GPU speeds models up unevenly, so at the same budget, one and two A100s select different routings on all three benchmarks. Refitting needs new cost measurements, but no new labels.&lt;/p&gt;

&lt;p&gt;Routing pays when no single model is both accurate enough and cheap enough for the budget. If one model already is, serve that model.&lt;/p&gt;

&lt;h2 id=&quot;cre-router-at-github&quot;&gt;CRE-Router at GitHub&lt;/h2&gt;

&lt;p&gt;The code, configurations, data and model outputs are on &lt;a href=&quot;https://github.com/ymoslem/CRE-Router&quot;&gt;GitHub&lt;/a&gt;. The training statistics measured in the paper ship with the repository, so you can fit a routing without a GPU.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/ymoslem/CRE-Router&quot;&gt;&lt;img src=&quot;https://github-readme-stats.vercel.app/api/pin/?theme=graywhite&amp;amp;username=ymoslem&amp;amp;repo=CRE-Router&quot; alt=&quot;CRE-Router&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fit a routing from the stored statistics:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/ymoslem/CRE-Router.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;CRE-Router
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
cre fit &lt;span class=&quot;nt&quot;&gt;--stats&lt;/span&gt; configs/telemath_stats_1xA100_Sep2026.json &lt;span class=&quot;nt&quot;&gt;--budget&lt;/span&gt; 25
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It prints the routing that a TPOT budget of 25 ms selects on TeleMath, and the quality estimators Stage 2 needs.&lt;/p&gt;

&lt;p&gt;To use the package without cloning the repository, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip install &quot;cre-router[full]&quot;&lt;/code&gt; installs everything needed for serving, including vLLM, so it needs a GPU machine. The README covers the full pipeline, from clustering and evaluation to serving with vLLM.&lt;/p&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://openreview.net/forum?id=ypRg1TvQaM&quot;&gt;Dynamic Model Routing and Cascading for Efficient LLM Inference: A Survey&lt;/a&gt; (Moslem &amp;amp; Kelleher, TMLR 2026)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/2606.27457&quot;&gt;Cluster, Route, Escalate: Cascaded Framework for Cost-Aware LLM Serving&lt;/a&gt; (Moslem et al., arXiv 2026)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://openreview.net/forum?id=cSimKw5p6R&quot;&gt;FrugalGPT: How to Use Large Language Models While Reducing Cost and Improving Performance&lt;/a&gt; (Chen et al., TMLR 2024)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;

&lt;p&gt;This work was funded by Huawei Ireland through a research collaboration with the ADAPT Centre at Trinity College Dublin.&lt;/p&gt;
</description>
        <pubDate>Wed, 28 Oct 2026 00:00:00 +0000</pubDate>
        <link>https://blog.yasmin.ie/cre-router/</link>
        <guid isPermaLink="true">https://blog.yasmin.ie/cre-router/</guid>
        
        
        <category>efficiency</category>
        
        <category>llm</category>
        
        <category>serving</category>
        
      </item>
    
      <item>
        <title>Disaggregated Serving</title>
        <description>&lt;p&gt;I recently tried disaggregated serving, a setup some production systems use to serve LLMs faster. Normally, each GPU both processes the prompt (prefill) and generates the answer (decode). In disaggregated serving, prefill and decode run on separate GPUs, so long new prompts do not slow down answers that are already streaming.&lt;/p&gt;

&lt;p&gt;In my test, I compared three standard replicas, one per GPU, with a disaggregated setup on the same three GPUs, where two GPUs process the prompts and pass the KV cache to a third GPU that only generates answers. Both setups received the same traffic.&lt;/p&gt;

&lt;div style=&quot;display:flex; flex-wrap:wrap; gap:12px; justify-content:center;&quot;&gt;
  &lt;img src=&quot;/static/img/disaggregation/disaggregated-serving-tpot.png&quot; alt=&quot;Median time per output token&quot; style=&quot;flex:1 1 280px; min-width:0; max-width:100%;&quot; /&gt;
  &lt;img src=&quot;/static/img/disaggregation/disaggregated-serving-ttft.png&quot; alt=&quot;Median time to first token&quot; style=&quot;flex:1 1 280px; min-width:0; max-width:100%;&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Median time per output token (TPOT) and time to first token (TTFT) as traffic grows on three A100s; dashed lines mark the latency limits.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;

&lt;p&gt;As traffic grew to 16 requests per second, the time per token (TPOT) with disaggregated serving stayed under 10 ms, while standard replicas slowed to 72 ms. The trade-off is that with disaggregation, the time to first token (TTFT) is a little longer, because each request waits for its KV cache to be passed from one GPU to another. At 12 requests per second, the first token took 0.54 s against 0.24 s for standard replicas.&lt;/p&gt;

&lt;p&gt;Counting only the requests served within 1 s to the first token and 20 ms per token (goodput), as in DistServe [1], disaggregated serving handled 10.0 requests per second against 7.6 for three standard replicas.&lt;/p&gt;

&lt;h2 id=&quot;chunked-prefill&quot;&gt;Chunked Prefill&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://docs.vllm.ai/en/stable/features/disagg_prefill/&quot;&gt;vLLM documentation&lt;/a&gt; notes that disaggregation does not improve raw throughput, and that tuning &lt;a href=&quot;https://docs.vllm.ai/en/stable/configuration/optimization/&quot;&gt;chunked prefill&lt;/a&gt;, which splits long prompts into smaller pieces, can reach a similar goal, although the right chunk size is hard to find. So I tried that too. With a 512-token chunk budget, standard replicas slowed to 29 ms instead of 72 ms, but still served fewer requests within the latency limits than the disaggregated setup, 8.0 against 10.0 requests per second.&lt;/p&gt;

&lt;h2 id=&quot;when-disaggregation-helps&quot;&gt;When Disaggregation Helps&lt;/h2&gt;

&lt;p&gt;Prefill and decode use the GPU differently, as prefill is compute-intensive and decode is memory-intensive [2]. Disaggregation is likely to help most when prompts are long, as in agentic workflows with a growing context, few-shot prompting, or questions over long documents. The DistServe authors [1] make the same argument for long contexts, since the KV cache to transfer grows linearly with the prompt, while prefill computation grows quadratically, so the transfer takes a shrinking share of the time. They also note that with only a few GPUs there is little room to rebalance prefill and decode, yet even on three GPUs, the split improved goodput for these long prompts. With short prompts, prefill takes little GPU time, so it barely slows the answers being generated. Passing the KV cache from one GPU to another then adds latency without much gain.&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;p&gt;The model is Qwen3-4B-Instruct, served with vLLM 0.19.0 on three A100 GPUs. Each prompt is a 25-shot TeleQnA question of about 3.5K tokens, with different examples per request. The disaggregated setup runs two prefill instances and one decode instance with vLLM’s &lt;a href=&quot;https://docs.vllm.ai/en/stable/features/nixl_connector_usage/&quot;&gt;NixlConnector&lt;/a&gt;, and the KV cache is sent over NVLink within one node. All setups use 128-token KV blocks with prefix caching off. Chunked prefill is on for the standard replicas (the vLLM default) and off on the prefill instances in disaggregated serving.&lt;/p&gt;

&lt;p&gt;Requests arrive at random (Poisson) at 2 to 16 requests per second, with 600 requests per rate and one run per rate. The requests-per-second figures count only the requests that meet both latency limits, at the best of the eight rates. Accuracy is the same in every setup, 67.7 to 68.5%. Real systems also turn on prefix caching, which lowers latency in either setup.&lt;/p&gt;

&lt;h2 id=&quot;disaggregation-in-vllm&quot;&gt;Disaggregation in vLLM&lt;/h2&gt;

&lt;p&gt;Each GPU runs its own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vllm serve&lt;/code&gt; instance with the same NixlConnector configuration. In my runs, the prefill instances processed whole prompts, with chunked prefill off, and since all instances share one machine, each needs its own NIXL side-channel port.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;KV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;{&quot;kv_connector&quot;: &quot;NixlConnector&quot;,
     &quot;kv_role&quot;: &quot;kv_both&quot;,
     &quot;kv_buffer_device&quot;: &quot;cuda&quot;}&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Prefill, GPU 0 (GPU 1 is the same, with ports 8101 and 5601)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;CUDA_VISIBLE_DEVICES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0 &lt;span class=&quot;nv&quot;&gt;VLLM_NIXL_SIDE_CHANNEL_PORT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5600 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  vllm serve Qwen/Qwen3-4B-Instruct-2507 &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 8100 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--block-size&lt;/span&gt; 128 &lt;span class=&quot;nt&quot;&gt;--no-enable-prefix-caching&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--no-enable-chunked-prefill&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--kv-transfer-config&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$KV&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Decode, GPU 2&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;CUDA_VISIBLE_DEVICES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2 &lt;span class=&quot;nv&quot;&gt;VLLM_NIXL_SIDE_CHANNEL_PORT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5602 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  vllm serve Qwen/Qwen3-4B-Instruct-2507 &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 8102 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--block-size&lt;/span&gt; 128 &lt;span class=&quot;nt&quot;&gt;--no-enable-prefix-caching&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--kv-transfer-config&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$KV&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The standard replicas run the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vllm serve&lt;/code&gt; command on each GPU, without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--kv-transfer-config&lt;/code&gt;, and the run with 512-token chunks adds &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--max-num-batched-tokens 512&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;vLLM does not route requests between the prefill and decode instances by itself, so a small proxy sits in front of them. It sends each request to a prefill instance with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max_tokens=1&lt;/code&gt;, then passes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kv_transfer_params&lt;/code&gt; that instance returns to the decode instance, which generates the answer. vLLM’s &lt;a href=&quot;https://github.com/vllm-project/vllm/blob/v0.19.0/tests/v1/kv_connector/nixl_integration/toy_proxy_server.py&quot;&gt;toy proxy server&lt;/a&gt; for NixlConnector is a good starting point.&lt;/p&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.usenix.org/conference/osdi24/presentation/zhong-yinmin&quot;&gt;DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving&lt;/a&gt; (Zhong et al., OSDI 2024)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/2311.18677&quot;&gt;Splitwise: Efficient Generative LLM Inference Using Phase Splitting&lt;/a&gt; (Patel et al., arXiv 2023)&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Fri, 23 Oct 2026 00:00:00 +0000</pubDate>
        <link>https://blog.yasmin.ie/disaggregated-serving/</link>
        <guid isPermaLink="true">https://blog.yasmin.ie/disaggregated-serving/</guid>
        
        
        <category>efficiency</category>
        
        <category>llm</category>
        
        <category>serving</category>
        
      </item>
    
      <item>
        <title>Iterative Layer Pruning for Efficient Inference</title>
        <description>&lt;p&gt;Model pruning is a compression technique, that aims to remove redundant components without significantly compromising the model’s performance or accuracy. This process facilitates efficient deployment of complex models by making them smaller and faster.&lt;/p&gt;

&lt;p&gt;Pruning is a hardware-agnostic compression approach. Unlike some other compression approaches such as quantisation, models resulting from structured pruning can be deployed on any modern GPU with similar performance gains. Moreover, pruning can be part of a sophisticated compression pipeline that incorporates other techniques such as quantisation and efficient fine-tuning (e.g. LoRA, QLoRA), which can lead to higher compression and efficiency levels.&lt;/p&gt;

&lt;p&gt;In this article, we will cover some insights from our two papers about Iterative Layer Pruning at IWSLT 2025 [1] and WMT 2025 [2].&lt;/p&gt;

&lt;h2 id=&quot;iterative-layer-pruning&quot;&gt;Iterative Layer Pruning&lt;/h2&gt;

&lt;p&gt;The process of Iterative Layer Pruning involves incrementally identifying and removing layers with minimal contribution to translation or generation quality, one layer at a time. The pruning process is usually followed by fine-tuning the resulting models on relevant training data to restore the translation quality. Moreover, knowledge distillation data from the baseline (teacher) model can be used to help the pruned (student) model to reach the quality of the teacher model.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../static/img/pruning/pruning-digram.png&quot; alt=&quot;pruning-digram&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;layer-importance-evaluation&quot;&gt;Layer Importance Evaluation&lt;/h2&gt;

&lt;p&gt;We conduct layer importance evaluation by measuring translation performance without each layer. The process is as follows:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Remove one layer of the model.&lt;/li&gt;
  &lt;li&gt;Evaluate the model (chrF++).&lt;/li&gt;
  &lt;li&gt;Repeat for the rest of the layers.&lt;/li&gt;
  &lt;li&gt;Prune the least important layer (best chrF++ without it).&lt;/li&gt;
  &lt;li&gt;Repeat #1 to #4 until reaching the pruning target.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;evaluation-results&quot;&gt;Evaluation Results&lt;/h2&gt;

&lt;p&gt;For translation from Czech to German (CES-DEU), pruning 8 layers and then fine-tuning the resulting model retains 98% of the translation quality (as measured by COMET), while achieving considerable speedup gains. Interestingly, for translation from English to Egyptian Arabic (ENG-ARZ), the model resulting from pruning up to 16 layers and then fine-tuning outperforms the Aya-Expanse-8B baseline for this language pair. Pruned models achieve up to ~2× speedup.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../static/img/pruning/pruning-results-wmt.png&quot; alt=&quot;pruning-results&quot; style=&quot;zoom:70%;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;knowledge-distillation&quot;&gt;Knowledge Distillation&lt;/h2&gt;

&lt;p&gt;Knowledge Distillation aims at transferring knowledge from a larger model (teacher) to a smaller one (student). In “sequence-level” knowledge distillation, the student model is trained to generate sequences that match the teacher’s sequence outputs. Fine-tuning the pruned models on a combination of authentic and synthetic data (from Aya-Expanse-32B) improved the Czech to German (CES-DEU) translation quality, with the 24-layer pruned model nearly matching the performance of the Aya-Expanse-8B
baseline.&lt;/p&gt;

&lt;div style=&quot;text-align:center;&quot;&gt;&lt;img src=&quot;../static/img/pruning/pruning-results-wmt-kd.png&quot; alt=&quot;pruning-results&quot; style=&quot;zoom:40%;&quot; /&gt;&lt;/div&gt;

&lt;h2 id=&quot;further-performance-gains&quot;&gt;Further performance gains&lt;/h2&gt;

&lt;p&gt;It is highly recommended to use an efficient inference engine such as vLLM, which outperforms inference with the Transformers framework. In both cases, pruned models demonstrate up to ~2× speedup.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../static/img/pruning/trasformers-vllm.png&quot; alt=&quot;vLLM&quot; style=&quot;zoom:70%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Moreover, you can quantise the pruned models for further compression. For example, in our IWSLT 2025 paper, we applied QLoRA after pruning the models. However, notice that low-precision quantisation (e.g. 4-bit and 8-bit) requires special hardware (e.g. H100 or H200) to observe performance gains.&lt;/p&gt;

&lt;h2 id=&quot;questions-and-answers&quot;&gt;Questions and Answers&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Q. Why iterative layer pruning instead of random or middle layer pruning?
    &lt;ul&gt;
      &lt;li&gt;A. Iterative layer pruning relies on layer importance analysis. Hence, only the layers with minimal contribution to the output quality can be removed. In our experiments, iterative layer pruning achieves better results than middle layer pruning.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Q. Can we prune other parts of the model other than layers?
    &lt;ul&gt;
      &lt;li&gt;A. There are two types of pruning, structured pruning and unstructured pruning. In structured pruning, you can remove whole layers, attention heads, or other entire computational blocks, while in unstructured pruning, you can remove individual weights from a neural network. While unstructured pruning can achieve higher compression rates, it requires specialised hardware for efficient deployment. On the contrary, models resulting from structure pruning can be deployed on standards GPUs.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Q. Is it better to fine-tune the baseline model &lt;em&gt;before&lt;/em&gt; pruning?
    &lt;ul&gt;
      &lt;li&gt;A. If your task, domain, or language is very different from the distribution of the baseline model, it is better to fine-tune the baseline model first. Otherwise, you can prune the baseline directly. On the contrary, fine-tuning &lt;em&gt;after&lt;/em&gt; pruning is always required to restore the quality of the baseline model.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Q. Can we fine-tune after each layer pruning step?
    &lt;ul&gt;
      &lt;li&gt;A. We experimented with both fine-tuning after each layer pruning step, and after a number of pruned layers. In both cases, there was no difference than just fine-tuning once after the end of the pruning process. This might be because of overfitting resulted from several fine-tuning passes.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Q. Can the same approach be applied to encoder-decoder models?
    &lt;ul&gt;
      &lt;li&gt;A. Yes, we applied this iterative layer pruning approach to both a decoder-only model, Aya-Expanse,  and an encoder-decoder model, Qwen2-Audio. However, for encoder-decoder models, we observed that only pruning the decoder leads to better overall performance.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;github-repository&quot;&gt;GitHub Repository&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/ymoslem/Model-Compression&quot;&gt;&lt;img src=&quot;https://github-readme-stats.vercel.app/api/pin/?theme=graywhite&amp;amp;username=ymoslem&amp;amp;repo=Model-Compression&quot; alt=&quot;Model-Compression&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://aclanthology.org/2025.iwslt-1.40/&quot;&gt;Efficient Speech Translation through Model Compression and Knowledge Distillation&lt;/a&gt; (Moslem, IWSLT 2025)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://aclanthology.org/2025.wmt-1.78/&quot;&gt;Iterative Layer Pruning for Efficient Translation Inference&lt;/a&gt; (Moslem et al., WMT 2025)&lt;/li&gt;
&lt;/ol&gt;

</description>
        <pubDate>Mon, 17 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://blog.yasmin.ie/iterative-layer-pruning/</link>
        <guid isPermaLink="true">https://blog.yasmin.ie/iterative-layer-pruning/</guid>
        
        
        <category>efficiency</category>
        
        <category>llm</category>
        
        <category>nmt</category>
        
        <category>speech</category>
        
      </item>
    
      <item>
        <title>Adaptive Translation and Terminology with Large Language Models</title>
        <description>&lt;p&gt;Translation clients expect consistent terminology and style, but a translation model that has never seen their approved translations cannot adapt in real time. Large language models (LLMs) offer a simple way around this. If the prompt includes a few similar approved translations, or a short glossary, the LLM follows them while translating the new sentence, with no retraining. This is called in-context learning. We studied this idea in several papers. This post collects what we found and what you can do with it.&lt;/p&gt;

&lt;h2 id=&quot;how-it-works&quot;&gt;How It Works&lt;/h2&gt;

&lt;p&gt;The approach needs a translation memory (TM), which is a collection of approved translations. For each new sentence, you retrieve the most similar sentences from the TM, called fuzzy matches. In our experiments, we compared sentence embeddings to find them. Then you put the matches in the prompt, followed by the new sentence. A prompt with two matches looks like this.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;English: &amp;lt;source fuzzy match 2&amp;gt;
Arabic: &amp;lt;target fuzzy match 2&amp;gt;
English: &amp;lt;source fuzzy match 1&amp;gt;
Arabic: &amp;lt;target fuzzy match 1&amp;gt;
English: &amp;lt;new source segment&amp;gt;
Arabic:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The most similar match (1) sits closest to the new sentence, and the model continues the pattern.&lt;/p&gt;

&lt;p&gt;Terminology works in a similar way. In our WMT 2023 submission, we gave the LLM an existing translation and asked it to use the required terms and leave everything else the same. This is a form of automatic post-editing, where an LLM revises the output of an MT system.&lt;/p&gt;

&lt;h2 id=&quot;what-the-results-show&quot;&gt;What the Results Show&lt;/h2&gt;

&lt;h3 id=&quot;similar-examples-beat-random-ones&quot;&gt;Similar examples beat random ones&lt;/h3&gt;

&lt;p&gt;In the EAMT 2023 paper, we tested GPT-3.5 on English to Arabic, Chinese, French, Kinyarwanda and Spanish, using TICO-19 as the TM. Few-shot translation with similar sentences beat few-shot translation with random sentences, and both beat zero-shot translation. Adding more matches helped (2, then 5, then 10), with smaller gains each time.&lt;/p&gt;

&lt;h3 id=&quot;an-llm-can-beat-a-strong-mt-system-depending-on-the-language&quot;&gt;An LLM can beat a strong MT system, depending on the language&lt;/h3&gt;

&lt;p&gt;Without examples, ModernMT translated better than GPT-3.5 for the four language pairs it supports. With 5 or 10 similar examples, GPT-3.5 beat ModernMT for English to Chinese, French and Spanish, even when ModernMT used a TM too. For Arabic it did not, partly because of how the GPT-3.5 tokenizer handles Arabic. Kinyarwanda is a low-resource language. How well an LLM supports your language pair matters a lot.&lt;/p&gt;

&lt;h3 id=&quot;if-the-llm-is-weaker-add-the-mt-output-to-the-prompt&quot;&gt;If the LLM is weaker, add the MT output to the prompt&lt;/h3&gt;

&lt;p&gt;For English to Arabic, putting the translation from an encoder-decoder system (OPUS) in the prompt, next to the similar examples, beat both the MT system alone and the LLM with examples alone. The same idea helped English to Chinese with Google’s translation. When the LLM was already clearly better, as for French and Spanish, adding MT output did not help.&lt;/p&gt;

&lt;h3 id=&quot;terminology-adherence-can-improve-with-some-care&quot;&gt;Terminology adherence can improve, with some care&lt;/h3&gt;

&lt;p&gt;An LLM extracted term pairs from sentence pairs, and over 95% were accurate in our human evaluation for Arabic, French and Spanish. Giving glossary terms in the prompt made the model use them more often, although forcing terms sometimes hurt grammar, and contradictory terms hurt quality.&lt;/p&gt;

&lt;p&gt;For the WMT 2023 terminology task (German to English, English to Czech, Chinese to English), our pipeline had four steps. An LLM generated synthetic sentences from the terminology, we fine-tuned an MT model on a mix of that data and generic data, we translated with it, and finally an LLM post-edited the output to insert missing terms. On the blind test set, the pipeline raised the average share of required terms used in the translations from 36.67% with the baseline model to 72.88%. Translation quality did not suffer, and it even improved according to automatic metrics (BLEU, chrF++ and COMET).&lt;/p&gt;

&lt;h3 id=&quot;a-small-open-model-can-be-enough&quot;&gt;A small open model can be enough&lt;/h3&gt;

&lt;p&gt;If you cannot send your data to a commercial API, you can fine-tune an open model. We fine-tuned Mistral 7B with QLoRA on 20,000 Spanish to English medical segments, half with plain prompts and half with one similar example. For this language pair and domain, in plain translation, the fine-tuned model matched NLLB 3.3B and beat gpt-3.5-turbo. With one similar example, it matched gpt-3.5-turbo and beat NLLB 3.3B. Training on both kinds of prompts means one model handles regular and adaptive translation.&lt;/p&gt;

&lt;h3 id=&quot;an-llm-is-not-always-the-answer&quot;&gt;An LLM is not always the answer&lt;/h3&gt;

&lt;p&gt;In a 2025 follow-up on medical translation for English to French, English to Portuguese, English to Swahili and Swahili to English, NLLB-200 3.3B beat every LLM we tested in the 7 to 8 billion parameter range in three of the four directions. Fine-tuning improved Mistral and Llama, but fine-tuned NLLB stayed ahead. Before you choose, compare a task-specific MT model with an LLM on your own language pair.&lt;/p&gt;

&lt;h2 id=&quot;code-and-data&quot;&gt;Code and Data&lt;/h2&gt;

&lt;p&gt;The fine-tuning code, data and evaluation scores are on GitHub. The repository covers fuzzy match retrieval with Sentence-Transformers and FAISS, fine-tuning, inference with CTranslate2 (and the ChatGPT API for comparison), and evaluation. It includes Spanish to English, plus English to French, Portuguese and Swahili, and Swahili to English.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/ymoslem/Adaptive-MT-LLM-Fine-tuning&quot;&gt;&lt;img src=&quot;https://github-readme-stats.vercel.app/api/pin/?theme=graywhite&amp;amp;username=ymoslem&amp;amp;repo=Adaptive-MT-LLM-Fine-tuning&quot; alt=&quot;Adaptive-MT-LLM-Fine-tuning&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;papers-and-citations&quot;&gt;Papers and Citations&lt;/h2&gt;

&lt;h3 id=&quot;adaptive-machine-translation-with-large-language-models&quot;&gt;Adaptive Machine Translation with Large Language Models&lt;/h3&gt;

&lt;p&gt;Moslem, Haque, Kelleher and Way. EAMT 2023. First preprint, January 2023. &lt;a href=&quot;https://aclanthology.org/2023.eamt-1.22.pdf&quot;&gt;PDF&lt;/a&gt;&lt;/p&gt;

&lt;details&gt;
  &lt;summary&gt;BibTeX&lt;/summary&gt;

  &lt;div class=&quot;language-bib highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;@inproceedings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;moslem-etal-2023-adaptive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Adaptive Machine Translation with Large Language Models&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Moslem, Yasmin  and
      Haque, Rejwanul  and
      Kelleher, John D.  and
      Way, Andy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;booktitle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Proceedings of the 24th Annual Conference of the European Association for Machine Translation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;month&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;jun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2023&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Tampere, Finland&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;publisher&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;European Association for Machine Translation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://aclanthology.org/2023.eamt-1.22/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;pages&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;227--237&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

&lt;/details&gt;

&lt;h3 id=&quot;domain-terminology-integration-into-machine-translation-leveraging-large-language-models&quot;&gt;Domain Terminology Integration into Machine Translation: Leveraging Large Language Models&lt;/h3&gt;

&lt;p&gt;Moslem, Romani, Molaei, Haque, Kelleher and Way. WMT 2023. First preprint, October 2023. &lt;a href=&quot;https://aclanthology.org/2023.wmt-1.82.pdf&quot;&gt;PDF&lt;/a&gt;&lt;/p&gt;

&lt;details&gt;
  &lt;summary&gt;BibTeX&lt;/summary&gt;

  &lt;div class=&quot;language-bib highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;@inproceedings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;moslem-etal-2023-domain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Domain Terminology Integration into Machine Translation: Leveraging Large Language Models&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Moslem, Yasmin  and
      Romani, Gianfranco  and
      Molaei, Mahdi  and
      Kelleher, John D.  and
      Haque, Rejwanul  and
      Way, Andy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;booktitle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Proceedings of the Eighth Conference on Machine Translation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;month&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2023&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Singapore&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;publisher&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Association for Computational Linguistics&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://aclanthology.org/2023.wmt-1.82/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;doi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10.18653/v1/2023.wmt-1.82&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;pages&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;902--911&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

&lt;/details&gt;

&lt;h3 id=&quot;fine-tuning-large-language-models-for-adaptive-machine-translation&quot;&gt;Fine-tuning Large Language Models for Adaptive Machine Translation&lt;/h3&gt;

&lt;p&gt;Moslem, Haque and Way. Preprint, December 2023, and a chapter of my thesis. &lt;a href=&quot;https://arxiv.org/pdf/2312.12740&quot;&gt;PDF&lt;/a&gt;&lt;/p&gt;

&lt;details&gt;
  &lt;summary&gt;BibTeX&lt;/summary&gt;

  &lt;div class=&quot;language-bib highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;moslem-etal-2023-fine-tuning-llms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{Fine-tuning Large Language Models for Adaptive Machine Translation}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
      &lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{Yasmin Moslem and Rejwanul Haque and Andy Way}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{2023}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;eprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{2312.12740}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;archivePrefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{arXiv}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;primaryClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{cs.CL}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{https://arxiv.org/abs/2312.12740}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

&lt;/details&gt;

&lt;h3 id=&quot;language-modelling-approaches-to-adaptive-machine-translation&quot;&gt;Language Modelling Approaches to Adaptive Machine Translation&lt;/h3&gt;

&lt;p&gt;Moslem. PhD thesis, Dublin City University, 2024. &lt;a href=&quot;https://arxiv.org/pdf/2401.14559&quot;&gt;PDF&lt;/a&gt;&lt;/p&gt;

&lt;details&gt;
  &lt;summary&gt;BibTeX&lt;/summary&gt;

  &lt;div class=&quot;language-bib highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;moslem-2024-adaptive-mt-llms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{Language Modelling Approaches to Adaptive Machine Translation, {PhD} thesis}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
      &lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{Yasmin Moslem}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{2024}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;eprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{2401.14559}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;archivePrefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{arXiv}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;primaryClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{cs.CL}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{https://arxiv.org/abs/2401.14559}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

&lt;/details&gt;

&lt;h3 id=&quot;domain-specific-translation-with-open-source-large-language-models-resource-oriented-analysis&quot;&gt;Domain-Specific Translation with Open-Source Large Language Models: Resource-Oriented Analysis&lt;/h3&gt;

&lt;p&gt;Wassie, Molaei and Moslem. Preprint, 2025. &lt;a href=&quot;https://arxiv.org/pdf/2412.05862&quot;&gt;PDF&lt;/a&gt;&lt;/p&gt;

&lt;details&gt;
  &lt;summary&gt;BibTeX&lt;/summary&gt;

  &lt;div class=&quot;language-bib highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;@article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;Wassie2025-DomainSpecific-Translation-LLM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;{Domain-Specific Translation with Open-Source Large Language Models: Resource-Oriented Analysis}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Wassie, Aman Kassahun and Molaei, Mahdi and Moslem, Yasmin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;month&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;may&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;year&lt;/span&gt;          &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;m&quot;&gt;2025&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;           &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://arxiv.org/abs/2412.05862&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;archivePrefix&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;arXiv&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;primaryClass&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;cs.CL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;eprint&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2412.05862&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

&lt;/details&gt;
</description>
        <pubDate>Wed, 10 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://blog.yasmin.ie/adaptive-mt/</link>
        <guid isPermaLink="true">https://blog.yasmin.ie/adaptive-mt/</guid>
        
        
        <category>nmt</category>
        
        <category>llm</category>
        
      </item>
    
      <item>
        <title>Purely Synthetic Bilingual Data for Machine Translation?</title>
        <description>&lt;p&gt;Fine-tuning a machine translation (MT) system for a specialised domain needs in-domain bilingual data, which is often scarce or missing. This post shows how a large language model can generate synthetic in-domain text, which you then back-translate and use for mixed fine-tuning. In our Arabic-English experiments, this improved translation quality in both directions, in automatic and human evaluation.&lt;/p&gt;

&lt;h2 id=&quot;method&quot;&gt;Method&lt;/h2&gt;

&lt;p&gt;Interestingly, when you feed such large language models with an in-domain sentence, they can generate more synthetic sentences, that simulate the domain and linguistic characteristics of the authentic sentence. In the research “&lt;strong&gt;&lt;em&gt;&lt;a href=&quot;https://aclanthology.org/2022.amta-research.2&quot;&gt;Domain-Specific Text Generation for Machine Translation&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;” (Moslem et al., 2022), we investigated the feasibility of this domain-specific text generation technique, when either no or limited bilingual in-domain dataset is available. We proposed a novel approach to domain adaptation leveraging state-of-the-art pre-trained language models to generate huge amounts of synthetic bilingual in-domain data with the goal of improving translation of in-domain texts. The process can be summarised in three simple steps:&lt;/p&gt;

&lt;h4 id=&quot;1-text-generation-target&quot;&gt;1. Text generation (target)&lt;/h4&gt;

&lt;blockquote&gt;
  &lt;p&gt;Generate target-side synthetic sentences using a large pre-trained language model.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When there is a small in-domain translation memory, you can use each target sentence as a prompt to generate text, that simulates the domain characteristics of the authentic in-domain data. If there is no translation memory at all, you can first forward-translate the source text to be translated, or a portion of it, using the baseline MT model.&lt;/p&gt;

&lt;h4 id=&quot;2-back-translation-source&quot;&gt;2. Back-translation (source)&lt;/h4&gt;

&lt;blockquote&gt;
  &lt;p&gt;Back-translate the synthetic target-side sentences into source language.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Combining the idea of in-domain text generation with back-translation, you can generate huge amounts of synthetic bilingual in-domain data, for both use cases.&lt;/p&gt;

&lt;h4 id=&quot;3-mixed-fine-tuning&quot;&gt;3. Mixed fine-tuning&lt;/h4&gt;

&lt;blockquote&gt;
  &lt;p&gt;Fine-tune the baseline model, on a mix of synthetic and authentic data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally, the baseline MT model should be fine-tuned using a combination of the synthetic bilingual in-domain dataset and a randomly sampled section of the original generic dataset.&lt;/p&gt;

&lt;h2 id=&quot;target-text-generation&quot;&gt;Target Text Generation&lt;/h2&gt;

&lt;p&gt;Among autoregressive language models, trained to predict the next word in a sequence, are BLOOM, GPT-3, and GPT-J. This code snippet shows how to load the GPT-J language model. You can use some efficient loading techniques such &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;float16&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;low_cpu_mem_usage&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;transformers&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GPTJForCausalLM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AutoTokenizer&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch&lt;/span&gt;


&lt;span class=&quot;n&quot;&gt;tokenizer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AutoTokenizer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_pretrained&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EleutherAI/gpt-j-6B&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;padding_side&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;left&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tokenizer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pad_token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenizer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eos_token&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;GPTJForCausalLM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_pretrained&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EleutherAI/gpt-j-6B&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                         &lt;span class=&quot;n&quot;&gt;revision&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;float16&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                         &lt;span class=&quot;n&quot;&gt;torch_dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;float16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                         &lt;span class=&quot;n&quot;&gt;low_cpu_mem_usage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                         &lt;span class=&quot;n&quot;&gt;cache_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;models_cache/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                         &lt;span class=&quot;n&quot;&gt;pad_token_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tokenizer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eos_token_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;half&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cuda&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Afterwards, you can use each target segment in the authentic in-domain dataset, to generate synthetic in-domain text. We use top-K and top-p sampling to generate diverse text sequences. Here, we set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;num_return_sequences&lt;/code&gt; to generate 5 sequences. Each sequence might include multiple sentences. You can then split these text sequences into several sentences using any sentence splitter.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;target_segment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;I am an example sentence that talks about something very specialized!&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;input_ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenizer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target_segment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add_special_tokens&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;return_tensors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_ids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cuda&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sample_outputs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;generate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_ids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                &lt;span class=&quot;n&quot;&gt;do_sample&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                                &lt;span class=&quot;n&quot;&gt;max_length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                                &lt;span class=&quot;n&quot;&gt;top_k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                                &lt;span class=&quot;n&quot;&gt;top_p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.95&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
                                &lt;span class=&quot;n&quot;&gt;num_return_sequences&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                &lt;span class=&quot;n&quot;&gt;early_stopping&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;generated_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenizer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch_decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sample_outputs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;skip_special_tokens&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The quality of the language model is important. Here, you can see examples of generated text, that is both linguistically correct, and factually accurate.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In March 2020, India ordered the countrywide shut down of all non-essential economic activities due to the spreading COVID-19 pandemic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;While the overall worldwide economic impact of COVID-19 will only be realized through the end of 2020 and the recovery phase in 2021, it is clear that certain parts of the world have been severely impacted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes, the generated text can be linguistically correct; however, numbers or names might be inaccurate.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Antiviral drugs are approved for pregnant women and should be considered for children younger than &lt;strong&gt;XX&lt;/strong&gt; years, although some are still being investigated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Scientists have found some species of &lt;strong&gt;unicorn&lt;/strong&gt; in Amazon rainforests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If there are only small mistakes, the generated synthetic data can be still used. Obviously, the better the quality of the text generated by the language model, the better the quality we can expect when fine-tuning the baseline MT model on this synthetic data.&lt;/p&gt;

&lt;h2 id=&quot;back-translation&quot;&gt;Back-Translation&lt;/h2&gt;

&lt;p&gt;Now, we have the target side of our new in-domain dataset. To generate the source side, use back-translation, into the other language direction. For back-translation, you can either train another MT model yourself, or use pre-trained models such as &lt;a href=&quot;https://github.com/Helsinki-NLP/Tatoeba-Challenge/blob/master/results/tatoeba-models-all.md&quot;&gt;OPUS models&lt;/a&gt;. Optionally, you can convert OPUS models to the &lt;a href=&quot;https://opennmt.net/CTranslate2/&quot;&gt;CTranslate2&lt;/a&gt; formate with quantisation to enhance efficiency.&lt;/p&gt;

&lt;p&gt;Basically, both the source and target sides of our new large in-domain dataset, consist of synthetic data. The target side is generated by a language model, while the source text is generated by back-translation, in the other language direction.&lt;/p&gt;

&lt;h2 id=&quot;mixed-fine-tuning&quot;&gt;Mixed Fine-Tuning&lt;/h2&gt;

&lt;p&gt;Now, it’s time to apply mixed fine-tuning to the baseline model.&lt;/p&gt;

&lt;p&gt;In other words, continue training our baseline model on a mix of (a) the synthetic bilingual in-domain dataset we obtained from the two previous steps, and (b) a randomly sampled portion of the original generic dataset. In our experiments, we oversampled the synthetic in-domain dataset, by a 9x ratio.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/img/mixed-fine-tuning-oversampling.png&quot; alt=&quot;Two donut charts for mixed fine-tuning with oversampling. By size, the generic dataset is 9x and the in-domain synthetic dataset 1x. By weight, the generic dataset is 0.1 and the synthetic dataset 0.9.&quot; /&gt;&lt;/p&gt;

&lt;center&gt;Mixed fine-tuning (Chu et al., 2017)&lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;To apply oversampling, we employed the dataset weights feature in OpenNMT-tf. If you are using OpenNMT-py or OpenNMT-tf, you can find more details in this &lt;a href=&quot;https://blog.yasmin.ie/domain-adaptation-mixed-fine-tuning/&quot;&gt;tutorial on mixed fine-tuning&lt;/a&gt; of MT models.&lt;/p&gt;

&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;

&lt;p&gt;In both scenarios, our proposed method achieves significant improvements, demonstrated by both automatic and human evaluations. As expected, Setup 1 (when there is a tiny bilingual dataset) reveals better results than Setup 2 (where there is no bilingual dataset at all). Still, models resulted from both setups outperform the baseline model.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/img/MT-ML-results.png&quot; alt=&quot;Table of evaluation results on TICO-19 for Arabic-English and English-Arabic. The baseline, Setup 1 and Setup 2 mixed fine-tuning are compared on spBLEU, chrF++, TER, COMET and human evaluation. Both setups outperform the baseline.&quot; /&gt;&lt;/p&gt;

&lt;center&gt;Evaluation results on the in-domain test set, TICO-19&lt;/center&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Previously, synthetic data for machine translation had been created either on the source-side only (forward-translation) or the target side only (back-translation). In some cases, researchers replaced a few words from the source and/or the target with synonyms or similar words. The assumption was that “relevant” monolingual data was available, which was not always the case!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In real-life scenarios&lt;/strong&gt;, things can get more complex. Usually, there is insufficient human-produced data to train or fine-tune high-quality MT systems. Production-level projects can be so specialised, while mining crawled monolingual datasets is inefficient and not necessarily helpful.&lt;/p&gt;

&lt;p&gt;This research work &lt;strong&gt;generates brand new synthetic data on both the source and target sides&lt;/strong&gt;. It employs large language models to put together coherent sentences similar to those to be translated in the current project. Then, the new synthetic data can be used to fine-tune production-level MT systems for domain-specific scenarios.  Feel free to check out our paper, &lt;a href=&quot;https://aclanthology.org/2022.amta-research.2&quot;&gt;&lt;em&gt;Domain-Specific Text Generation for Machine Translation&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;download-scripts&quot;&gt;Download Scripts&lt;/h2&gt;

&lt;p&gt;You can download our scripts and configuration files at &lt;a href=&quot;https://github.com/ymoslem/MT-LM&quot;&gt;GitHub&lt;/a&gt;. If you have applied the method and/or have questions, please let me know.&lt;/p&gt;

&lt;h2 id=&quot;citation&quot;&gt;Citation&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@inproceedings{moslem-etal-2022-domain,
    title = &quot;Domain-Specific Text Generation for Machine Translation&quot;,
    author = &quot;Moslem, Yasmin  and
      Haque, Rejwanul  and
      Kelleher, John  and
      Way, Andy&quot;,
    booktitle = &quot;Proceedings of the 15th biennial conference of the Association for Machine Translation in the Americas (Volume 1: Research Track)&quot;,
    month = sep,
    year = &quot;2022&quot;,
    address = &quot;Orlando, USA&quot;,
    publisher = &quot;Association for Machine Translation in the Americas&quot;,
    url = &quot;https://aclanthology.org/2022.amta-research.2&quot;,
    pages = &quot;14--30&quot;,
    abstract = &quot;Preservation of domain knowledge from the source to target is crucial in any translation workflow. It is common in the translation industry to receive highly specialized projects, where there is hardly any parallel in-domain data. In such scenarios where there is insufficient in-domain data to fine-tune Machine Translation (MT) models, producing translations that are consistent with the relevant context is challenging. In this work, we propose a novel approach to domain adaptation leveraging state-of-the-art pretrained language models (LMs) for domain-specific data augmentation for MT, simulating the domain characteristics of either (a) a small bilingual dataset, or (b) the monolingual source text to be translated. Combining this idea with back-translation, we can generate huge amounts of synthetic bilingual in-domain data for both use cases. For our investigation, we use the state-of-the-art Transformer architecture. We employ mixed fine-tuning to train models that significantly improve translation of in-domain texts. More specifically, in both scenarios, our proposed methods achieve improvements of approximately 5-6 BLEU and 2-3 BLEU, respectively, on the Arabic-to-English and English-to-Arabic language pairs. Furthermore, the outcome of human evaluation corroborates the automatic evaluation results&quot;,
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 12 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://blog.yasmin.ie/synthetic-data-machine-translation/</link>
        <guid isPermaLink="true">https://blog.yasmin.ie/synthetic-data-machine-translation/</guid>
        
        
        <category>nmt</category>
        
        <category>llm</category>
        
      </item>
    
      <item>
        <title>Translation Auto-suggestions: What do Linguists Think?</title>
        <description>&lt;p&gt;Translation auto-suggestion and auto-completion are among the important features that can help translators better utilize Machine Translation (MT) systems. In a Computer-Aided Translation (CAT) environment, a translator can make use of the MT word auto-suggestion feature as follows. By typing a few words, or clicking a word in a proposed MT translation, a list of suggestions is displayed. By selecting one of the word suggestions from the list, the rest of the translation is modified accordingly.&lt;/p&gt;

&lt;p&gt;In a user survey we designed and distributed via social media networks, we asked participants whether they thought an MT word-level auto-suggestions feature could be helpful, and provided a simple definition and an illustrative image. If their answer was “Yes”, the respondent was asked to specify a reason. By the time of writing this article, we received 41 responses to our survey. While we do not believe this survey is enough to justify introducing an auto-suggestions feature into every MT system, it can be an indicator as to why some users think such a feature could be helpful.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../static/img/autosuggest.png&quot; alt=&quot;MT-autosuggestions&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To answer the question, “&lt;em&gt;Which of the following best describes you?&lt;/em&gt;” 46.3% (19) of the respondents chose “&lt;em&gt;Translator/Linguist&lt;/em&gt;”, 31.7% (13) selected “&lt;em&gt;NLP Engineer/Researcher&lt;/em&gt;”, and the rest 22% (9) were other “&lt;em&gt;MT Users&lt;/em&gt;”, not included in the two aforementioned categories.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../static/img/autosuggest-categories.png&quot; alt=&quot;users&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Among the respondents to the survey, 90.2% (37) answered “Yes” to the question “&lt;em&gt;In general, do you believe that a word-level auto-suggestions feature is helpful?&lt;/em&gt;” The figure below shows the breakdown of answers to the question, “&lt;em&gt;Why do you believe that a word-level auto-suggestions feature can be helpful?&lt;/em&gt;” taking into consideration those who answered “No” to the previous question.&lt;/p&gt;

&lt;p&gt;Out of the 37 persons who believed a word-level auto-suggestions feature can be helpful, 40.5% (15) of the respondents specified that it can give them some inspiration. This answer is specifically interesting as it is not constrained by time-saving benefits; hence, it focusses more on effectiveness rather than efficiency. The respondent that answered with “Other” mentioned that it allows them to look for alternative senses or phrasings, especially when they suspect the initial translation is bad, and referred to this as “human in the loop”.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../static/img/autosuggest-why.png&quot; alt=&quot;autosuggest-why&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Respondents were allowed to give extra comments; among the notable comments were:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;small&gt;I think word-level suggestions can be a useful feature, particularly when the target language can have several translations of a single source word.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;small&gt;Word-level suggestions can be helpful, but sometimes you end up spending a lot of time figuring out if the MT suggestion is a valid translation in that context. So, I’m not really sure yet how I feel about it.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;small&gt;It’s useful, as long as it’s seen as a suggestion, and not inserted in the target where the translator is typing.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Among the respondents who answered “For me, it is easier or faster than typing”, comments included:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;small&gt;Though most of the time; the suggestions are lousy.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;small&gt;I don’t think it gives me inspiration as I mostly need it for structures, not single words.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;small&gt;Auto-suggestion does not have to come from machine translation. History is much more useful.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The last comment above might be referring to the fact that in some CAT tools, auto-suggestions can also include glossary terms, and translation memory sub-segments, which encourages further research efforts to investigate methods to enhance leveraging and interaction between various translation resources in human-in-the-loop environments.&lt;/p&gt;

&lt;p&gt;We hope this survey will inspire future user studies to look deeper into how diverse users of MT and CAT tools prefer to utilize certain features, such as auto-suggestions, and the value they seek. More aspects should be taken into consideration such as language pairs, translation workflows, and user interfaces. This can help improve these features to better support linguists and other MT users and boost their productivity as well as translation quality.&lt;/p&gt;

&lt;h3 id=&quot;citation&quot;&gt;Citation&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@inproceedings{moslem2022-autosuggest,
    title = &quot;Word-Level Auto-Completion: What can we achieve out of the box?&quot;,
    author = &quot;Moslem, Yasmin  and
      Haque, Rejwanul  and
      Way, Andy&quot;,
    booktitle = &quot;In Proceedings of the Seventh Conference on Machine Translation&quot;,
    month = Dec,
    year = &quot;2022&quot;,
    address = &quot;Abu Dhabi, UAE&quot;,
    publisher = &quot;Association for Computational Linguistics&quot;,
    url = &quot;https://arxiv.org/abs/2210.12802&quot;,
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 24 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://blog.yasmin.ie/translation-autosuggestion-survey/</link>
        <guid isPermaLink="true">https://blog.yasmin.ie/translation-autosuggestion-survey/</guid>
        
        
        <category>nmt</category>
        
      </item>
    
      <item>
        <title>Machine Translation Robustness</title>
        <description>&lt;p&gt;Let’s talk briefly about the concept of “Robustness” of neural machine translation (NMT) systems. While robustness should be emphasized when building any NMT system, even high-resource languages with plenty of data can still face linguistic challenges.&lt;/p&gt;

&lt;h2 id=&quot;what-does-nmt-robustness-mean&quot;&gt;What does NMT “Robustness” mean?&lt;/h2&gt;

&lt;p&gt;It simply means that a certain NMT engine can handle a specific linguistic feature, found in the input to be translated. This feature might not be naturally occurring in the training data. Among examples of linguistic features we want our NMT model to be robust while translating are: domain terminology, proper names, number formats, text case, misspellings, code switching (between two languages), and untranslatables such as tags, email addresses, etc.&lt;/p&gt;

&lt;h2 id=&quot;how-can-we-improve-nmt-robustness&quot;&gt;How can we improve NMT robustness?&lt;/h2&gt;

&lt;p&gt;The first step to machine translation robustness is defining the issues that your model frequently encounters when translating a certain type of text. This step is underestimated, and in my opinion it is a sign of the maturity of production-level operations.&lt;/p&gt;

&lt;p&gt;This goes beyond numerical human evaluation, and moves a step further towards defining specific types of issues. In simple words, human evaluators are asked to mention a clear reason why they think a translation should be ranked as 3 out of 5, for example. At the beginning, they might be provided with common lists, but they should also have the option to add more issues, that can be integrated into that list later. Such explanations should not be vague; they should be precise in a way allowing MT engineers to fix these issues. Problematic words should be marked; sometimes the track-changes feature is used. The main question is: &lt;em&gt;What is the most critical issue in this translation?&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-can-we-improve-nmt-robustness-1&quot;&gt;How can we improve NMT “Robustness”?&lt;/h2&gt;

&lt;p&gt;In the findings of the WMT2020 Robustness Shared Task, under the “Common Trends” section, Specia et al. (2020) stated: “Participating systems were trained following a standard recipe, i) using big-transformer models, ii) boosting performance with tagged back-translation, iii) continued training with filtered data and in-domain data (where available), iv) ensembling different models to obtain further improvements.”&lt;/p&gt;

&lt;p&gt;In this sense, data augmentation techniques can be helpful, and then you integrate this new data into the NMT system, via combining or fine-tuning.&lt;/p&gt;

&lt;p&gt;As training a new system frequently might not be feasible, it is common in some companies to temporarily apply on-the-fly find-replace operations on translations, until the next training is possible. Some researchers also suggest making such on-the-fly handling easier by injecting the training data with certain placeholders, to be able to replace later. To apply this, in a portion of the training data, natural tags (html, xml, long numbers, etc.) are replaced with pseudo-tags (e.g. &amp;lt;t0&amp;gt;, &amp;lt;t1&amp;gt;, &amp;lt;t2&amp;gt;, …). These pseudo-tags should be also added as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user_defined_symbols&lt;/code&gt; to the SentencePiece model (cf. SPM &lt;a href=&quot;https://github.com/google/sentencepiece/blob/master/doc/options.md&quot;&gt;options&lt;/a&gt;). At inference time, it is easy to define and replace these tags with untraslatables during pre-processing and post-processing steps. On a relevant note, activating the SentencePiece option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;split_digits&lt;/code&gt; helps with copying longer numbers without intervention, while the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;byte_fallback&lt;/code&gt; sometimes helps with irregular characters in the training data.&lt;/p&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://themqm.org/&quot;&gt;MQM&lt;/a&gt; - Multidimensional Quality Metrics (&lt;a href=&quot;https://aclanthology.org/2013.tc-1.6/&quot;&gt;Lommel et al., 2013&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Training Neural Machine Translation to Apply Terminology Constraints (&lt;a href=&quot;https://aclanthology.org/P19-1294/&quot;&gt;Dinu et al., 2019&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Improving Robustness in Real-World Neural Machine Translation Engines (&lt;a href=&quot;https://aclanthology.org/W19-6727/&quot;&gt;Gupta et al., 2019&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;How Should Markup Tags Be Translated? (&lt;a href=&quot;https://aclanthology.org/2020.wmt-1.138/&quot;&gt;Hanneman and Dinu, 2020&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Evaluating Robustness to Input Perturbations for Neural Machine Translation (&lt;a href=&quot;https://arxiv.org/abs/2005.00580&quot;&gt;Niu et al., 2020&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Findings of the WMT 2020 Shared Task on Machine Translation Robustness (&lt;a href=&quot;https://aclanthology.org/2020.wmt-1.4/&quot;&gt;Specia et al., 2020&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Business Critical Errors: A Framework for Adaptive Quality Feedback (&lt;a href=&quot;https://aclanthology.org/2022.amta-upg.17/&quot;&gt;Stewart et al., 2022&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Improve MT for Search with Selected Translation Memory using Search Signals (&lt;a href=&quot;https://aclanthology.org/2022.amta-upg.9/&quot;&gt;Zhang 2022&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 28 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://blog.yasmin.ie/machine-translation-robustness/</link>
        <guid isPermaLink="true">https://blog.yasmin.ie/machine-translation-robustness/</guid>
        
        
        <category>nmt</category>
        
      </item>
    
      <item>
        <title>Preparing MT Data with SentencePiece and PyTorch</title>
        <description>&lt;p&gt;This tutorial shows how to prepare parallel data for training a machine translation (MT) model with PyTorch. We filter the data, train SentencePiece subword models, convert the text to IDs, split it into training, validation and test sets, and build padded batches. The code uses only SentencePiece and plain PyTorch.&lt;/p&gt;

&lt;p&gt;Updated October 2026. An earlier version of this tutorial used Torchtext. Torchtext development has stopped, and version 0.18 (April 2024) was the last stable release. This version replaces the Torchtext functions with SentencePiece and PyTorch, and the steps stay the same. The code was tested with Python 3.11, PyTorch 2.9 and SentencePiece 0.2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of Contents:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#installation-and-importing&quot;&gt;Installation and Importing&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#filtering-data&quot;&gt;Filtering Data&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#subword-tokenization&quot;&gt;Subword Tokenization&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#training-sentencepiece-models&quot;&gt;Training SentencePiece Models&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#subwording-data-with-the-sentencepiece-models&quot;&gt;Subwording Data with the SentencePiece Models&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#data-preparation-function&quot;&gt;Data Preparation Function&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#vocabulary&quot;&gt;Vocabulary&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#build-batches&quot;&gt;Build Batches&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#bucketing-optional&quot;&gt;Bucketing&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#next-steps&quot;&gt;Next Steps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;installation-and-importing&quot;&gt;Installation and Importing&lt;/h2&gt;

&lt;p&gt;Let’s first install PyTorch and SentencePiece:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip3 &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;torch sentencepiece
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, import what we need.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sentencepiece&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spm&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch.utils.data&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataLoader&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch.nn.utils.rnn&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pad_sequence&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;filtering-data&quot;&gt;Filtering Data&lt;/h2&gt;

&lt;p&gt;It is highly recommended you filter your data before training an MT model. The purpose is mainly to remove empty rows, duplicates, and too-long source/target rows. You can either use one of Moses scripts (&lt;a href=&quot;https://github.com/moses-smt/mosesdecoder/blob/master/scripts/training/clean-corpus-n.perl&quot;&gt;clean-corpus-n.perl&lt;/a&gt;), or one of my MT Preparation scripts (&lt;a href=&quot;https://github.com/ymoslem/MT-Preparation/blob/main/filtering/filter.py&quot;&gt;filter.py&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&quot;subword-tokenization&quot;&gt;Subword Tokenization&lt;/h2&gt;

&lt;p&gt;Subwording is a type of text tokenization. Dividing words into subword units help decrease the size of vocabulary and hence minimize out-of-vocabulary situations. Among subwording techniques are Byte-Pair Encoding (BPE) (&lt;a href=&quot;https://www.aclweb.org/anthology/P16-1162&quot;&gt;Sennrich et al., 2016&lt;/a&gt;) and unigram language model (&lt;a href=&quot;https://aclanthology.org/P18-1007/&quot;&gt;Kudo, 2018&lt;/a&gt;), supported by several tools. &lt;a href=&quot;https://github.com/google/sentencepiece&quot;&gt;SentencePiece&lt;/a&gt; is one of the popular tools used for subwording text.&lt;/p&gt;

&lt;h3 id=&quot;training-sentencepiece-models&quot;&gt;Training SentencePiece Models&lt;/h3&gt;

&lt;p&gt;Unless you use a shared vocabulary, you have to train one model for the source text and another model for the target text. The following code creates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source.spm.model&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source.spm.vocab&lt;/code&gt; for the source, and the same two files for the target.&lt;/p&gt;

&lt;p&gt;The IDs of the special tokens are set explicitly, so we know them later: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;unk&amp;gt;&lt;/code&gt; is 0, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;pad&amp;gt;&lt;/code&gt; is 1, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;s&amp;gt;&lt;/code&gt; (start of a sentence) is 2, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;/s&amp;gt;&lt;/code&gt; (end of a sentence) is 3.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;source_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;source.txt&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;target_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;target.txt&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vocab_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32000&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;source&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;spm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SentencePieceTrainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;model_prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.spm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vocab_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vocab_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;model_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;unigram&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;unk_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pad_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bos_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eos_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Done! Training SentencePiece models completed.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Training prints a long log. You can choose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;model_type=&quot;bpe&quot;&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;unigram&quot;&lt;/code&gt; for Byte-Pair Encoding.&lt;/p&gt;

&lt;h6 id=&quot;tip-what-to-do-if-vocabulary-size-too-high&quot;&gt;💡Tip: What to do if “Vocabulary size too high”?&lt;/h6&gt;

&lt;p&gt;If you are experimenting with a very small file, a vocabulary size of 32000 might be too big. SentencePiece stops with an error such as “Vocabulary size too high (32000). Please set it to a value &amp;lt;= 664.” The message tells you the largest size your data supports, so use a value up to that number. Obviously, it would be better to add more data.&lt;/p&gt;

&lt;h6 id=&quot;tip-what-if-the-corpus-is-very-large&quot;&gt;💡Tip: What if the corpus is very large?&lt;/h6&gt;

&lt;p&gt;SentencePiece does not need every sentence to train a good model. For a corpus of tens of millions of sentences, train on a random sample by adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input_sentence_size=10000000&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shuffle_input_sentence=True&lt;/code&gt; to the arguments of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SentencePieceTrainer.train&lt;/code&gt;. For languages with a large character set, such as Chinese or Japanese, keep the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;character_coverage=0.9995&lt;/code&gt;. For languages with a small character set, you can set it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.0&lt;/code&gt;.&lt;/p&gt;

&lt;h6 id=&quot;tip-how-to-rather-build-a-shared-vocabulary&quot;&gt;💡Tip: How to rather build a shared vocabulary?&lt;/h6&gt;

&lt;p&gt;To train one model on both languages, give SentencePiece both files, separated by a comma. This works well for languages that share a script or many words.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;spm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SentencePieceTrainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_file&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target_file&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model_prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;shared.spm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vocab_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vocab_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;unigram&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;unk_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pad_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bos_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eos_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then use the same model for the source and the target in the next steps.&lt;/p&gt;

&lt;h3 id=&quot;subwording-data-with-the-sentencepiece-models&quot;&gt;Subwording Data with the SentencePiece Models&lt;/h3&gt;

&lt;p&gt;Load the trained models.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;source_sp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SentencePieceProcessor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model_file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;source.spm.model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SentencePieceProcessor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model_file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;target.spm.model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;encode&lt;/code&gt; method converts text into subword pieces or into IDs, depending on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;out_type&lt;/code&gt;. Both of the following accept a single sentence or a list of sentences.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;This is an example.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;This is an example.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For training, we use the IDs.&lt;/p&gt;

&lt;h2 id=&quot;data-preparation-function&quot;&gt;Data Preparation Function&lt;/h2&gt;

&lt;p&gt;This function reads the source and target files, optionally lowercases them, converts the sentences to IDs, and splits the data into training, development and test sets. The pairs are shuffled together before splitting, so the source and target sentences stay aligned.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;prepare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;source_lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;target_lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Length of source and target lines must be the same!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;source_lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;target_lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Subword the sentences, i.e. convert them to lists of IDs
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;source_ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;target_ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target_lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Shuffle the pairs together, then split into dev, test, and train
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_ids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_ids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;dev_dataset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;test_dataset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;train_dataset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;train_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_dataset&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, we can use this function to prepare the data.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;dev_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;test_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;train_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_dataset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prepare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                                   &lt;span class=&quot;n&quot;&gt;source_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s print some data statistics.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Training dataset size: %s&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;train_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;&quot;Dev dataset size: %s&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;&quot;Test dataset size: %s&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; | &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, let’s print a few lines of the test dataset.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;vocabulary&quot;&gt;Vocabulary&lt;/h2&gt;

&lt;p&gt;With SentencePiece, the vocabulary is the model itself, so there is no separate step to build one. Each model already maps every piece to an ID and back.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Source vocabulary size:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_piece_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Target vocabulary size:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_piece_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# IDs of the special tokens
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pad, unk, bos, eos:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pad_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unk_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bos_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eos_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Convert IDs back to pieces
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id_to_piece&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Keep the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.model&lt;/code&gt; files together with your trained model, because you need the same ones at translation time. Unknown pieces map to the ID of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;unk&amp;gt;&lt;/code&gt; automatically.&lt;/p&gt;

&lt;p&gt;At translation time, encode the source with the source model, and decode the IDs that the model generates with the target model.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Special tokens such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;s&amp;gt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;/s&amp;gt;&lt;/code&gt; are left out of the decoded text.&lt;/p&gt;

&lt;h2 id=&quot;build-batches&quot;&gt;Build Batches&lt;/h2&gt;

&lt;p&gt;As training large datasets is time consuming, we build batches from the training data. First, let’s determine the device, the batch size, and the maximum length of the source and target sentences.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cuda&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cuda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_available&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;cpu&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# examples
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# tokens in source or target
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pad_idx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pad_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Very long or empty sentences make training slower and less stable, so we keep only training pairs of a reasonable length.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;train_dataset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;train_dataset&lt;/span&gt;
                 &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_len&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The collate function builds one batch. It adds the start and end tokens, which help the model know when to stop, and converts each sentence to a tensor. Sentences are padded to the longest sentence in the batch, so all of them have the same length.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;collate_batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sources&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;targets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bos_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eos_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bos_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target_sp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eos_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sources&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;targets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;sources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pad_sequence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sources&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;padding_value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pad_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;targets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pad_sequence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;targets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;padding_value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pad_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sources&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;targets&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, let’s create the data loaders, which yield batches. Each takes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collate_batch&lt;/code&gt; function that we have just created as an argument. We shuffle the training data only.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;train_dataloader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataLoader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;train_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collate_fn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collate_batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;valid_dataloader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataLoader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collate_fn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collate_batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;test_dataloader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataLoader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collate_fn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collate_batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you want to test a data loader, you can use the following code. In your training loop, move each batch to the device.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_dataloader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each shape is (sequence length, batch size), because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pad_sequence&lt;/code&gt; puts the sequence first. If your model expects the batch first, pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;batch_first=True&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pad_sequence&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;bucketing-optional&quot;&gt;Bucketing [optional]&lt;/h3&gt;

&lt;p&gt;Sentences in a random batch have very different lengths, so a large part of each batch can be padding. Bucketing groups sentences of similar lengths in the same batch, which reduces the padding and speeds up training. The following function shuffles the data, sorts chunks of it by source length, cuts the chunks into batches, and shuffles the batches.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bucket_batches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chunk_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rng&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rng&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;batches&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chunk_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chunk_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;batches&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;rng&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batches&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since the batches are already formed, set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;batch_size=None&lt;/code&gt; in the data loader. Create the data loader again for each epoch, with a different &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;seed&lt;/code&gt;, to get new batches.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;train_dataloader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataLoader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bucket_batches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;train_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                              &lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collate_fn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collate_batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h2&gt;

&lt;p&gt;You can now feed these batches to a PyTorch model, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;torch.nn.Transformer&lt;/code&gt;. If you prefer to train with a toolkit, see &lt;a href=&quot;/opennmt-tutorial/&quot;&gt;How to Build and Deploy Machine Translation Models&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Sat, 09 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://blog.yasmin.ie/mt-data-preparation/</link>
        <guid isPermaLink="true">https://blog.yasmin.ie/mt-data-preparation/</guid>
        
        
        <category>nmt</category>
        
      </item>
    
      <item>
        <title>How to Build and Deploy Machine Translation Models</title>
        <description>&lt;p&gt;This is a Neural Machine Translation (NMT) tutorial with &lt;a href=&quot;https://github.com/OpenNMT/OpenNMT-py&quot;&gt;OpenNMT-py&lt;/a&gt; and relevant tools. It covers data preprocessing, model training, evaluation, and deployment. The tutorial was put together as part of a mentorship activity I organised in 2022.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/ymoslem/OpenNMT-Tutorial&quot;&gt;&lt;img src=&quot;https://github-readme-stats.vercel.app/api/pin/?theme=graywhite&amp;amp;username=ymoslem&amp;amp;repo=OpenNMT-Tutorial&quot; alt=&quot;NMT-tutorial&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;fundamentals&quot;&gt;Fundamentals&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Data Processing (&lt;a href=&quot;https://github.com/ymoslem/OpenNMT-Tutorial/blob/main/1-NMT-Data-Processing.ipynb&quot;&gt;notebook&lt;/a&gt;, &lt;a href=&quot;https://github.com/ymoslem/MT-Preparation&quot;&gt;repository&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;NMT Model Training with OpenNMT-py (&lt;a href=&quot;https://github.com/ymoslem/OpenNMT-Tutorial/blob/main/2-NMT-Training.ipynb&quot;&gt;notebook&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Translation/Inference with CTranslate2 (&lt;a href=&quot;https://gist.github.com/ymoslem/60e1d1dc44fe006f67e130b6ad703c4b&quot;&gt;code&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;MT Evaluation with BLEU (&lt;a href=&quot;https://blog.yasmin.ie/compute-bleu-score/&quot;&gt;tutorial&lt;/a&gt;, &lt;a href=&quot;https://github.com/ymoslem/MT-Evaluation&quot;&gt;repository&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Simple Web UI (&lt;a href=&quot;https://blog.yasmin.ie/nmt-web-interface/&quot;&gt;tutorial&lt;/a&gt;, &lt;a href=&quot;https://github.com/ymoslem/OpenNMT-Web-Interface&quot;&gt;repository&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;advanced-topics&quot;&gt;Advanced Topics&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Running TensorBoard with OpenNMT (&lt;a href=&quot;https://blog.yasmin.ie/tensorboard/&quot;&gt;tutorial&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Low-Resource Neural Machine Translation (&lt;a href=&quot;https://blog.yasmin.ie/low-resource-nmt/&quot;&gt;tutorial&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Domain Adaptation with Mixed Fine-tuning (&lt;a href=&quot;https://blog.yasmin.ie/domain-adaptation-mixed-fine-tuning/&quot;&gt;tutorial&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Overview of Domain Adaptation Techniques (&lt;a href=&quot;https://amtaweb.org/wp-content/uploads/2020/11/NMTDomainAdaptationTechniques.pdf&quot;&gt;tutorial&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Multilingual Machine Translation (&lt;a href=&quot;https://blog.yasmin.ie/multilingual-nmt/&quot;&gt;tutorial&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Preparing Data for PyTorch Models with SentencePiece (&lt;a href=&quot;/mt-data-preparation/&quot;&gt;tutorial&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Using Pre-trained NMT models with CTranslate2 (&lt;a href=&quot;https://gist.github.com/ymoslem/a414a0ead0d3e50f4d7ff7110b1d1c0d&quot;&gt;tutorial&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 15 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://blog.yasmin.ie/opennmt-tutorial/</link>
        <guid isPermaLink="true">https://blog.yasmin.ie/opennmt-tutorial/</guid>
        
        
        <category>nmt</category>
        
      </item>
    
      <item>
        <title>Mixed Fine-Tuning - Domain Adaptation That Works!</title>
        <description>&lt;p&gt;Training a robust generic model is an interesting task. However, when you want to customize your Machine Translation model to observe the terminology and style of a certain domain or client, Domain Adaptation comes to life. In previous posts, we discussed several approaches to Domain Adaptation. In this post, we are going to concentrate on a very effective approach called Mixed Fine-Tuning, originally proposed by &lt;a href=&quot;https://aclanthology.org/P17-2061/&quot;&gt;Chu et al., 2017&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Regular fine-tuning of an NMT model usually consists of two steps:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Building a baseline NMT model, e.g. a generic model.&lt;/li&gt;
  &lt;li&gt;Continuing training the baseline NMT model on an in-domain dataset.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, fine-tuning in this way can lead to “catastrophic forgetting”, i.e. the model overfits the in-domain data, starts forgetting the information learned from the baseline data, and loses generalization. So in practice, when you compare its quality to the baseline model, the in-domain model would give a better BLEU score and human evaluation for translation of sentences very similar to the in-domain training dataset, but worse BLEU score for out-of-domain sentences or even new in-domain sentences.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Unlike plain fine-tuning, in the Mixed Fine-Tuning approach (Chu et al., 2017), you randomly sample a portion from the generic data you used to train the baseline model, and use it during the fine-tuning step along with the in-domain dataset. Over-sampling the in-domain data is the main trick.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The training procedure of the Mixed Fine-tuning approach is as follows:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Train a baseline NMT model on out-of-domain data until convergence.&lt;/li&gt;
  &lt;li&gt;Continue training the NMT baseline model on a &lt;em&gt;mix&lt;/em&gt; of in-domain and out-of-domain data (by &lt;em&gt;oversampling&lt;/em&gt; the in-domain data) until convergence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In NMT tools, such as OpenNMT and MarianMT, &lt;em&gt;dataset weights&lt;/em&gt; can be used to replicate over-sampling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dataset Counts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Generic Dataset: 1,000,000 sentences&lt;/li&gt;
  &lt;li&gt;In-domain Dataset: 100,000 sentences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use weights 1:10 so that the training takes 1 sentence from the bigger generic dataset, and 10 sentences from the smaller in-domain dataset.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Generic Dataset: 1&lt;/li&gt;
  &lt;li&gt;In-domain Dataset: 10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this example, we sequentially sample 1 example from the “Generic Dataset” and 10 examples from the “In-domain Dataset” and so on. By giving the “In-domain Dataset” a higher weight, the model can learn the style and terminology from the in-domain dataset while still be able to generalize, i.e. output high-quality translations for out-of-domain sentences.&lt;/p&gt;

&lt;p&gt;Setting the dataset weights differs from one tool to another. In &lt;a href=&quot;https://opennmt.net/OpenNMT-py/FAQ.html#how-can-i-weight-different-corpora-at-training&quot;&gt;OpenNMT-py&lt;/a&gt;, dataset weights are set as numbers as in the aforementioned example. In &lt;a href=&quot;https://opennmt.net/OpenNMT-tf/data.html?highlight=weighted#weighted-dataset&quot;&gt;OpenNMT-tf&lt;/a&gt;, dataset weights are set as ratios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Further notes on the Mixed Fine-tuning approach&lt;/strong&gt; (feel free to experiment with something different, though!)&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The approach works well for in-domain datasets between 50k and 500k. For very small in-domain datasets, this approach might &lt;em&gt;not&lt;/em&gt; work well; for bigger in-domain datasets, you might want to try different weights; and for very big in-domain datasets, you can just use the in-domain dataset only, but enrich it with missing aspects like shorter sentences, if needed.&lt;/li&gt;
  &lt;li&gt;If your baseline training data is too big, you randomly extract 10 times the size of the in-domain data.&lt;/li&gt;
  &lt;li&gt;If both the generic and in-domain data are available before training the baseline, we build the vocabulary and SentencePiece models on all datasets, both generic and in-domain datasets.&lt;/li&gt;
  &lt;li&gt;During fine-tuning, we extract a dev/validation dataset from the in-domain dataset only.&lt;/li&gt;
  &lt;li&gt;After fine-tuning, we use two test datasets, one that we used for the out-of-domain baseline, and one extracted from the in-domain dataset, to make sure the model works in both cases.&lt;/li&gt;
  &lt;li&gt;To alleviate “catastrophic forgetting” on generic data, consider averaging the baseline model with the fine-tuned model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Among the advantages of the Mixed Fine-tuning approach is that this fine-tuned NMT in-domain model still works well on both unseen in-domain data and general/out-of-domain data. Moreover, the approach can be fully automated (e.g. for various clients) once you verify it for your use cases.&lt;/p&gt;

&lt;p&gt;It is worth mentioning that we have successfully applied the Mixed Fine-Tuning approach, proposed by Chu et al. (2017), in production-level scenarios in the industry. We also employed it in a number of our Domain Adaptation and Low-Resource NMT papers such as &lt;a href=&quot;https://aclanthology.org/2020.icon-adapmt.4/&quot;&gt;Haque et al. (2020)&lt;/a&gt; in combination with other approaches, through which we achieved the first place at ICON 2020 shared task, as well as &lt;a href=&quot;https://aclanthology.org/2022.amta-research.2/&quot;&gt;Moslem et al. (2022)&lt;/a&gt; where we used synthetic in-domain data.&lt;/p&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Axelrod, A., He, X., &amp;amp; Gao, J. (2011). Domain Adaptation via Pseudo In-Domain Data Selection. &lt;em&gt;Proceedings of the 2011 Conference on Empirical Methods in Natural Language Processing&lt;/em&gt;, 355–362. &lt;a href=&quot;https://aclanthology.org/D11-1033&quot;&gt;https://aclanthology.org/D11-1033&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Chinea-Ríos, M., Peris, Á., &amp;amp; Casacuberta, F. (2017). Adapting Neural Machine Translation with Parallel Synthetic Data. &lt;em&gt;Proceedings of the Second Conference on Machine Translation&lt;/em&gt;, 138–147. &lt;a href=&quot;https://doi.org/10.18653/v1/W17-4714&quot;&gt;https://doi.org/10.18653/v1/W17-4714&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Chu, C., Dabre, R., &amp;amp; Kurohashi, S. (2017). An Empirical Comparison of Domain Adaptation Methods for Neural Machine Translation. Proceedings of the 55th Annual Meeting of the Association for Computational Linguistics (Volume 2: Short Papers), 385–391. &lt;a href=&quot;https://doi.org/10.18653/v1/P17-2061&quot;&gt;https://doi.org/10.18653/v1/P17-2061&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Freitag, M., &amp;amp; Al-Onaizan, Y. (2016). Fast Domain Adaptation for Neural Machine Translation. In &lt;em&gt;arXiv [cs.CL]&lt;/em&gt;. arXiv. &lt;a href=&quot;http://arxiv.org/abs/1612.06897&quot;&gt;http://arxiv.org/abs/1612.06897&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Haque, R., Moslem, Y., &amp;amp; Way, A. (2020). Terminology-Aware Sentence Mining for NMT Domain Adaptation: ADAPT’s Submission to the Adap-MT 2020 English-to-Hindi AI Translation Shared Task. Proceedings of the 17th International Conference on Natural Language Processing (ICON): Adap-MT 2020 Shared Task, 17–23. &lt;a href=&quot;https://aclanthology.org/2020.icon-adapmt.4&quot;&gt;https://aclanthology.org/2020.icon-adapmt.4&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Kobus, C., Crego, J., &amp;amp; Senellart, J. (2017). Domain Control for Neural Machine Translation. &lt;em&gt;Proceedings of Recent Advances in Natural Language Processing&lt;/em&gt;, 372–378. &lt;a href=&quot;http://arxiv.org/abs/1612.06140&quot;&gt;http://arxiv.org/abs/1612.06140&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Luong, M.-T., &amp;amp; Manning, C. 2015. Stanford neural machine translation systems for spoken language domains. &lt;em&gt;Proceedings of the 12th International Workshop on Spoken Language Translation: Evaluation Campaign&lt;/em&gt;, 76–79. &lt;a href=&quot;https://aclanthology.org/2015.iwslt-evaluation.11&quot;&gt;https://aclanthology.org/2015.iwslt-evaluation.11&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Moslem, Y., Haque, R., Kelleher, J., &amp;amp; Way, A. (2022). Domain-Specific Text Generation for Machine Translation. &lt;em&gt;Proceedings of the 15th Biennial Conference of the Association for Machine Translation in the Americas (Volume 1: Research Track)&lt;/em&gt;, 14–30. &lt;a href=&quot;https://aclanthology.org/2022.amta-research.2&quot;&gt;https://aclanthology.org/2022.amta-research.2&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Moslem, Y. (2024). Language Modelling Approaches to Adaptive Machine Translation. In &lt;em&gt;arXiv [cs.CL]&lt;/em&gt;. arXiv. &lt;a href=&quot;http://arxiv.org/abs/2401.14559&quot;&gt;http://arxiv.org/abs/2401.14559&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Saunders, D. (2022). Domain Adaptation and Multi-Domain Adaptation for Neural Machine Translation: A Survey. &lt;em&gt;Journal of Artificial Intelligence Research&lt;/em&gt;, &lt;em&gt;75&lt;/em&gt;, 351–424. &lt;a href=&quot;https://doi.org/10.1613/jair.1.13566&quot;&gt;https://doi.org/10.1613/jair.1.13566&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Sennrich, R., Haddow, B., &amp;amp; Birch, A. (2016a). Controlling Politeness in Neural Machine Translation via Side Constraints. &lt;em&gt;Proceedings of the 2016 Conference of the North AMerican Chapter of the Association for Computational Linguistics: Human Language Technologies&lt;/em&gt;, 35–40. &lt;a href=&quot;https://doi.org/10.18653/v1/N16-1005&quot;&gt;https://doi.org/10.18653/v1/N16-1005&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Sennrich, R., Haddow, B., &amp;amp; Birch, A. (2016b). Improving Neural Machine Translation Models with Monolingual Data. &lt;em&gt;Proceedings of the 54th Annual Meeting of the Association for Computational Linguistics (Volume 1: Long Papers)&lt;/em&gt;, 86–96. &lt;a href=&quot;https://doi.org/10.18653/v1/P16-1009&quot;&gt;https://doi.org/10.18653/v1/P16-1009&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Thu, 06 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://blog.yasmin.ie/domain-adaptation-mixed-fine-tuning/</link>
        <guid isPermaLink="true">https://blog.yasmin.ie/domain-adaptation-mixed-fine-tuning/</guid>
        
        
        <category>nmt</category>
        
      </item>
    
  </channel>
</rss>
