我编写了以下 bash 脚本,将输入文件分成两个,用于以下签名: splitfiles 文件名 0.9 其中 0.9 是训练集比例,其余是测试集。
function splitfiles()
{
length=$(wc -l $1)
top=$(($length*$2))
head -n $top $1 >traintxt
tail -n $(($length-$top)) $1 >valtxt
}
但它对文件 110-1.txt 抛出以下错误
$splitfiles 110-1.txt 0.9
bash:4756073 110-1.txt * 0.9:表达式中的语法错误(错误标记为“110-1.txt * 0.9”)
如果你想随机分割文件,你可以使用另一个 awk oneliner 来使用 awk 的 rand() 函数来概率性地分割文件:
awk '{if(rand()<0.9) {print > output.train} else {print > output.test}}' input
如果您需要参数化文件名,这会更复杂一些,因为您需要使用 -v 开关将它们传递给 awk:
in="myLibSVMdata"
train="$in.train"
test="$in.test"
awk -v train="$train" -v test="$test" '{if(rand()<0.9) {print > train} else {print > test}}' $in
更换
wc -l $1
由
wc -l < $1
避免输出中出现文件名。
您可以使用此
awk
命令来替换您的 splitfiles
函数:
awk -v lines=$(wc -l < "$1") -v fact="$2" 'NR <= lines * fact {
print > "traintxt"; next} {print > "valtxt"}' "$1"
对 @Rob Challen 的答案稍作改进:我将其做成一个函数,其中比率也是可控的,并且我们确信训练和测试/开发文件已创建并可以附加到其中。
function split_train_val(){
in=$1
train=$2
test=$3
ratio=$4
echo "" > $train
echo "" > $test
awk -v train="$train" -v test="$test" '{if(rand()<$ratop) {print > train} else {print > test}}' $in
}
如果@Rob Challen 的答案对您不起作用,请尝试以下操作:
awk '{if(rand()<0.9) {print $0 > "output.train"} else {print $0 > "output.test"}}' input
这是数据科学和机器学习项目中常用的操作。我最终为它编写了一个实用程序。希望您觉得它有用!
function split() {
filepath=$1;
filepath_train=$2;
filepath_valid=$3;
filepath_test=$4;
num_lines=$(wc -l $filepath | sed 's/^ *//g' | cut -d' ' -f1);
line_nr_train_end=$(($num_lines * 4/5))
line_nr_valid_end=$(($num_lines * 4/5 + 1 + $num_lines * 1/10))
cat $filepath | awk -v line_nr_train_end=$line_nr_train_end 'NR <= line_nr_train_end' > $filepath_train;
cat $filepath | awk -v line_nr_train_end=$line_nr_train_end -v line_nr_valid_end=$line_nr_valid_end 'NR > line_nr_train_end && NR <= line_nr_valid_end' > $filepath_valid;
cat $filepath | awk -v line_nr_valid_end=$line_nr_valid_end 'NR > line_nr_valid_end' > $filepath_test;
}
您将该方法称为
split filetosplit.txt train.txt valid.txt test.txt