从两个文本文件(平行语料库)中随机抽样N行
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从两个文本文件(平行语料库)中随机抽样N行相关的知识,希望对你有一定的参考价值。
我一次又一次地面临着从两个文件(即来自平行语料库;句子根据行号对齐)对特定行数(例如N
)进行采样的问题。
对于从事(神经)机器翻译研究的人来说,这是一项常见而频繁的任务。
我想知道一种快速有效的方法从并行语料库中取样(即选择)N
行,可能来自命令行。
例如,如果我们想以一致的方式从两个文件中选择4
行,我们可以在行号3
,12
,17
,23
中对行进行采样。这应该从这两个文件中提供这些行。此外,将这个参数N
作为任意参与是很好的,这样我们就可以根据需要改变它。此外,应对这些线进行采样而不重复。并且,需要采样的所需行数N
将始终小于两个文件中的总行数,其中两个文件总是具有相等的行数。
一旦我们对所需的行进行采样,还希望从两个未被采样的文件中获取行(即获得在随机采样中未选择的其余行)。
这样做的整个想法是以一致的方式对两个文件进行采样,以便保留它们的行对齐。 (即选择
N
线和N-T
线,其中T
是总线数。)
其中N
是所需的采样行数而不重复,而N-T
是尚未采样的其余行。
我该怎么做呢?提前致谢!
如果你不允许重复,最好使用shuffle算法。为此目的已经有一个工具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"))
- 参数$ 1,2,3:样本数,filename1和2。
- 使用wc -l和cat的maxline,因为那时我们不需要删除文件名。 (没有无用的猫奖,这里)。
- seq x y生成从x到y的序列,此处为1到maxlines。没有一个错误的错误,因为wc,源,从sed(稍后)开始计数。
- shuf -e将这些数字洗牌,而不是期望它们行
- 对于样品数量,从前面拉亚麻布, 但是对它们进行排序,以便sed只需要遍历文件一次。 后缀“p”代表sed。
- 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的数组索引,您可以迭代两个行数组并进行比较 - 或者无论作业是什么。
以上是关于从两个文本文件(平行语料库)中随机抽样N行的主要内容,如果未能解决你的问题,请参考以下文章
Spark MLlib之水塘抽样算法(Reservoir Sampling)
pandas对dataframe的数据行进行随机抽样(Random Sample of Rows):使用sample函数进行数据行随机抽样(有放回的随机抽样,replacement)