[英]Randomly sample N lines from two text files(parallel corpus) consistently
一次又一次,我面對取樣線特定數量的問題(假設N
)兩個文件(即從平行語料庫 ;句子按照行號排列) 一致 。
對於從事(神經)機器翻譯研究的人員來說,這是一項常見且頻繁的任務。
我想知道一種快速有效的方法來從並行語料庫(可能是從命令行)中采樣(即選擇) N
行。
例如,如果我們想選擇4
兩個文件行以一致的方式,我們可以在采樣行號線3
, 12
, 17
, 23
。 這應該使我們從兩個文件中獲得這些行。 同樣,最好將此參數N
為任意值,以便我們可以根據需要更改它。 此外,這些行應不重復采樣。 並且,需要采樣的行數N
總是小於兩個文件中的總行數,其中兩個文件的總行數總是相等。
一旦我們對所需的行進行了采樣,還需要從兩個文件中都未采樣的行中獲取(即獲取未在隨機采樣中選擇的其余行)。
這樣做的整體思路是以一致的方式對兩個文件進行采樣,以保留其線對齊。 (即,選擇
N
行和NT
行,其中T
是總行數。)
其中N
是要重復采樣的期望行數, NT
是其余未采樣的行。
我將如何去做呢? 提前致謝!
如果不允許重復,則最好使用隨機播放算法。 為此已經有一個工具shuf
。
例如,
$ shuf -n 10 file
將從文件中隨機選擇10行給您(按隨機順序)。 您的請求有兩個附加約束,首先應該對選擇進行排序,其次,對於下一次運行,選擇必須保持一致。 對於第二個要求,您可以向shuf
提供隨機性源以兩次獲得相同的序列。 為了排序,我們依靠自己的力量...
$ shuf -n 10 --random-source=file <(cat -n file1) | sort -n | cut -f2- > sample1
$ shuf -n 10 --random-source=file <(cat -n file2) | sort -n | cut -f2- > sample2
將以正確的順序為您提供相同的采樣行。 出於隨機性考慮,您可以使用一個文件或任何其他第三個文件(但兩次運行都應相同)。
另一種選擇是將兩個文件粘貼在一起,然后隨機播放一次,然后拆分樣本。
$ paste -d'|' file1 file2 | cat -n | shuf -n 10 | sort -n | cut -f2 > sample
$ cut -d'|' -f1 sample > sample1
$ cut -d'|' -f2 sample > sample2
要獲取未選擇的行,您需要保留行號。 使用第二種選擇
$ paste -d'|' file1 file2 | cat -n | shuf -n 10 | sort -n > n_samples
$ cut -f2- n_samples > samples
$ awk 'NR==FNR{a[$1];next} !(FNR in a)' <(cut -f1 n_samples) samples > notselected
您可以像以前一樣拆分樣本和未選擇的文件。
使用第一種替代方法,將從文件中未選擇的行寫入具有相同名稱和擴展名“ .not”的文件
$ cat -n file1 | shuf -n 10 --random-source=file | sort -n > n_sample1
$ cut -f2- n_sample1 > sample1
$ cat -n file2 | shuf -n 10 --random-source=file | sort -n | cut -f2- > sample2
$ awk 'NR==FNR {a[$1];next}
!(FNR in a) {print > FILENAME".not"}' <(cut -f1 n_sample1) sample1 sample2
#!/bin/bash
samples=$1
file1="$2"
file2="$3"
maxlines=$(cat "$file1" | wc -l)
nums=($(shuf -e $(echo $(seq 1 $maxlines))))
lines=$(for i in $(seq 1 $samples); do echo ${nums[$i]}p" "; done | sort -n)
sed -n "$lines" "$file1"
sed -n "$lines" "$file2"
#rows1=($(sed -n "$lines" "$file1"))
#rows2=($(sed -n "$lines" "$file2"))
sed -n,對於一個11行的小文件,sample = 4,看起來像這樣:
sed -n 3p 4p 5p 7p mul.sh
如果您不希望按文件輸出而是按行輸出,則將它們收集在數組中:
rows1=($(sed -n "$lines" "$file1"))
rows2=($(sed -n "$lines" "$file2"))
這樣,sed仍然只需要遍歷可能較大的文件一次。 使用從0到$ sample-1的數組索引,您可以遍歷兩個行數組並進行比較-或執行任何工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.