使用 Bash 创建机器学习模型

Bash、Tcsh 或 Zsh 可以帮助您为机器学习做好准备。
123 位读者喜欢这篇文章。
bash logo on green background

Opensource.com

机器学习是一种强大的计算能力,可以预测或预测传统算法难以处理的事情。机器学习之旅从收集和准备数据(大量数据)开始,然后基于这些数据构建数学模型。虽然可以使用多种工具来完成这些任务,但我喜欢使用 shell

Shell 是使用定义的语言执行操作的接口。可以使用交互方式或脚本方式调用此语言。shell 的概念是在 1970 年代的 Unix 操作系统中引入的。一些最流行的 shell 包括 BashtcshZsh。它们适用于包括 Linux、macOS 和 Windows 在内的所有操作系统,这使它们具有很高的可移植性。在本练习中,我将使用 Bash。

本文介绍了如何使用 shell 进行数据收集和数据准备。无论您是寻求高效工具的数据科学家,还是希望将您的技能用于机器学习的 shell 专家,我都希望您能在此处找到有价值的信息。

本文中的示例问题是创建一个机器学习模型来预测美国各州的气温。它使用 shell 命令和脚本来执行以下数据收集和数据准备步骤

  1. 下载数据
  2. 提取必要的字段
  3. 聚合数据
  4. 制作时间序列
  5. 创建训练、测试和验证数据集

您可能会问,当您可以使用 Python 等机器学习编程语言完成所有这些工作时,为什么要使用 shell 来完成呢?这是一个很好的问题。如果使用像 shell 这样简单、友好、丰富的技术执行数据处理,那么数据科学家将只专注于机器学习建模,而不是语言的细节。

先决条件

首先,您需要安装一个 shell 解释器。如果您使用 Linux 或 macOS,它将已经安装,并且您可能已经熟悉它。如果您使用 Windows,请尝试 MinGWCygwin

有关更多信息,请参见

  • Bash 教程 在 opensource.com 上
  • Steve Parker (Bourne shell 的创建者) 编写的官方 shell 脚本教程
  • Linux 文档项目的 Bash 初学者指南
  • 如果您需要特定命令的帮助,请在 shell 中键入 <命令名> --help 以获得帮助;例如:ls --help

开始

现在您的 shell 已设置好,您可以开始为机器学习温度预测问题准备数据。

1. 下载数据

本教程的数据来自美国国家海洋和大气管理局 (NOAA)。您将使用最近 10 个完整年份的数据来训练您的模型。数据源位于 https://www1.ncdc.noaa.gov/pub/data/ghcn/daily/by_year/,数据为 .csv 格式,并经过 gzipped 压缩。

使用 shell 脚本下载并解压缩数据。使用您喜欢的文本编辑器创建一个名为 download.sh 的文件,然后粘贴以下代码。代码中的注释解释了命令的作用

#!/bin/sh
# This is called hashbang. It identifies the executor used to run this file.
# In this case, the script is executed by shell itself.
# If not specified, a program to execute the script must be specified. 
# With hashbang: ./download.sh;  Without hashbang: sh ./download.sh;

FROM_YEAR=2010
TO_YEAR=2019

year=$FROM_YEAR
# For all years one by one starting from FROM_YEAR=2010 upto TO_YEAR=2019
while [ $year -le $TO_YEAR ]
do
    # show the year being downloaded now
    echo $year
    # Download
    wget https://www1.ncdc.noaa.gov/pub/data/ghcn/daily/by_year/${year}.csv.gz
    # Unzip
    gzip -d ${year}.csv.gz
    # Move to next year by incrementing
    year=$(($year+1))
done

备注

  • 如果您位于代理服务器之后,请查阅 Mark Grennan 的 操作指南,并使用
    export http_proxy=http://username:password@proxyhost:port/
    export https_proxy=https://username:password@proxyhost:port/
  • 确保所有标准命令都已在您的 PATH 中(例如 /bin/usr/bin)。如果不是,请 设置您的 PATH
  • Wget 是一个用于从命令行连接到 Web 服务器的实用程序。如果您的系统上未安装 Wget,请 下载它
  • 确保您已安装 gzip,这是一个用于压缩和解压缩的实用程序。

运行此脚本以下载、提取并使 10 年的数据以 CSV 形式可用

$ ./download.sh
2010
--2020-10-30 19:10:47--  https://www1.ncdc.noaa.gov/pub/data/ghcn/daily/by_year/2010.csv.gz
Resolving www1.ncdc.noaa.gov (www1.ncdc.noaa.gov)... 205.167.25.171, 205.167.25.172, 205.167.25.178, ...
Connecting to www1.ncdc.noaa.gov (www1.ncdc.noaa.gov)|205.167.25.171|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 170466817 (163M) [application/gzip]
Saving to: '2010.csv.gz'

     0K .......... .......... .......... .......... ..........  0% 69.4K 39m57s
    50K .......... .......... .......... .......... ..........  0%  202K 26m49s
   100K .......... .......... .......... .......... ..........  0% 1.08M 18m42s

...

ls 命令列出文件夹的内容。使用 ls 20*.csv 列出所有名称以 20 开头并以 .csv 结尾的文件。

$ ls 20*.csv
2010.csv  2011.csv  2012.csv  2013.csv  2014.csv  2015.csv  2016.csv  2017.csv  2018.csv  2019.csv

2. 提取平均温度

从美国地区的 CSV 文件中提取 TAVG(平均温度)数据

extract_tavg_us.sh

#!/bin/sh

# For each file with name that starts with "20" and ens with ".csv"
for csv_file in `ls 20*.csv`
do
    # Message that says file name $csv_file is extracted to file TAVG_US_$csv_file
    # Example: 2010.csv extracted to TAVG_US_2010.csv
    echo "$csv_file -> TAVG_US_$csv_file"
    # grep "TAVG" $csv_file: Extract lines in file with text "TAVG"
    # |: pipe
    # grep "^US": From those extract lines that begin with text "US"
    # > TAVG_US_$csv_file: Save xtracted lines to file TAVG_US_$csv_file
    grep "TAVG" $csv_file | grep "^US" > TAVG_US_$csv_file
done

此脚本

$ ./extract_tavg_us.sh
2010.csv -> TAVG_US_2010.csv
...
2019.csv -> TAVG_US_2019.csv

创建以下文件

$ ls TAVG_US*.csv
TAVG_US_2010.csv  TAVG_US_2011.csv  TAVG_US_2012.csv  TAVG_US_2013.csv
TAVG_US_2014.csv  TAVG_US_2015.csv  TAVG_US_2016.csv  TAVG_US_2017.csv
TAVG_US_2018.csv  TAVG_US_2019.csv

以下是 TAVG_US_2010.csv 的前几行

$ head TAVG_US_2010.csv
USR0000AALC,20100101,TAVG,-220,,,U,
USR0000AALP,20100101,TAVG,-9,,,U,
USR0000ABAN,20100101,TAVG,12,,,U,
USR0000ABCA,20100101,TAVG,16,,,U,
USR0000ABCK,20100101,TAVG,-309,,,U,
USR0000ABER,20100101,TAVG,-81,,,U,
USR0000ABEV,20100101,TAVG,-360,,,U,
USR0000ABEN,20100101,TAVG,-224,,,U,
USR0000ABNS,20100101,TAVG,89,,,U,
USR0000ABLA,20100101,TAVG,59,,,U,

head 命令是一个实用程序,用于显示文件的前几行(默认情况下,10 行)。

数据包含的信息超出您的需要。通过消除第 3 列(因为所有数据都是平均温度)和第 5 列及之后的列来限制列数。换句话说,保留第 1 列(气候站)、第 2 列(日期)和第 4 列(记录的温度)。

key_columns.sh

#!/bin/sh

# For each file with name that starts with "TAVG_US_" and ens with ".csv"
for csv_file in `ls TAVG_US_*.csv`
do
    echo "Exractiing columns $csv_file"
    # cat $csv_file: 'cat' is to con'cat'enate files - here used to show one year csv file
    # |: pipe
    # cut -d',' -f1,2,4: Cut columns 1,2,4 with , delimitor
    # > $csv_file.cut: Save to temporary file
    | > $csv_file.cut: 
    cat $csv_file | cut -d',' -f1,2,4 > $csv_file.cut
    # mv $csv_file.cut $csv_file: Rename temporary file to original file
    mv $csv_file.cut $csv_file
    # File is processed and saved back into the same
    # There are other ways to do this
    # Using intermediate file is the most reliable method.
done

运行脚本

$ ./key_columns.sh
Extracting columns TAVG_US_2010.csv
...
Extracting columns TAVG_US_2019.csv

TAVG_US_2010.csv 的前几行(已删除不需要的数据)是

$ head TAVG_US_2010.csv
USR0000AALC,20100101,-220
USR0000AALP,20100101,-9
USR0000ABAN,20100101,12
USR0000ABCA,20100101,16
USR0000ABCK,20100101,-309
USR0000ABER,20100101,-81
USR0000ABEV,20100101,-360
USR0000ABEN,20100101,-224
USR0000ABNS,20100101,89
USR0000ABLA,20100101,59

日期采用字符串形式 (YMD)。为了正确训练您的模型,您的算法需要识别逗号分隔的 Y,M,D 形式的日期字段(例如,20100101 变为 2010,01,01)。您可以使用 sed 实用程序转换它们。

date_format.sh

for csv_file in `ls TAVG_*.csv`
do
    echo Date formatting $csv_file
    # This inserts , after year
    sed -i 's/,..../&,/' $csv_file
    # This inserts , after month
    sed -i 's/,....,../&,/' $csv_file
done

运行脚本

$ ./date_format.sh
Date formatting TAVG_US_2010.csv
...
Date formatting TAVG_US_2019.csv

TAVG_US_2010.csv 的前几行(采用逗号分隔的日期格式)是

$ head TAVG_US_2010.csv
USR0000AALC,2010,01,01,-220
USR0000AALP,2010,01,01,-9
USR0000ABAN,2010,01,01,12
USR0000ABCA,2010,01,01,16
USR0000ABCK,2010,01,01,-309
USR0000ABER,2010,01,01,-81
USR0000ABEV,2010,01,01,-360
USR0000ABEN,2010,01,01,-224
USR0000ABNS,2010,01,01,89
USR0000ABLA,2010,01,01,59

3. 聚合各州的平均温度数据

天气数据来自位于美国城市的气候站,但您想预测整个州的气温。要将气候站数据转换为州数据,首先将气候站映射到其州。

使用 wget 下载气候站列表

$ wget ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/daily/ghcnd-stations.txt

使用 grep 实用程序提取美国站点以查找美国列表。以下命令搜索以文本 "US." 开头的行。> 是一个 重定向,将输出写入文件,在本例中,写入名为 us_stations.txt 的文件

$ grep "^US" ghcnd-stations.txt > us_stations.txt

此文件是为漂亮的打印而创建的,因此列分隔符不一致

$ head us_stations.txt
US009052008  43.7333  -96.6333  482.0 SD SIOUX FALLS (ENVIRON. CANADA)
US10RMHS145  40.5268 -105.1113 1569.1 CO RMHS 1.6 SSW
US10adam001  40.5680  -98.5069  598.0 NE JUNIATA 1.5 S
...

使用 cat 打印文件,使用 tr 挤压重复项并输出到临时文件,并将临时文件重命名回原始文件,从而使它们保持一致,所有操作都在一行中完成

$ cat us_stations.txt | tr -s ' ' > us_stations.txt.tmp; cp us_stations.txt.tmp us_stations.txt;

命令输出的前几行

$ head us_stations.txt
US009052008 43.7333 -96.6333 482.0 SD SIOUX FALLS (ENVIRON. CANADA)
US10RMHS145 40.5268 -105.1113 1569.1 CO RMHS 1.6 SSW
US10adam001 40.5680 -98.5069 598.0 NE JUNIATA 1.5 S
...

这包含很多信息(GPS 坐标等),但您只需要站点代码和州。使用 cut

$ cut -d' ' -f1,5 us_stations.txt > us_stations.txt.tmp; mv us_stations.txt.tmp us_stations.txt;

命令输出的前几行

$ head us_stations.txt
US009052008 SD
US10RMHS145 CO
US10adam001 NE
US10adam002 NE
...

将其制作成 CSV 并使用 sed 将空格更改为逗号分隔符

$ sed -i s/' '/,/g us_stations.txt

命令输出的前几行

$ head us_stations.txt
US009052008,SD
US10RMHS145,CO
US10adam001,NE
US10adam002,NE
...

虽然您使用了多个命令来完成这些任务,但可以在一次运行中执行所有步骤。自己尝试一下。

现在,使用 AWK 将站点代码替换为其州位置,AWK 在功能上对于大型数据处理具有很高的性能。

station_to_state_data.sh

#!/bin/sh

for DATA_FILE in `ls TAVG_US_*.csv`

do
    echo ${DATA_FILE}
    awk -v FILE=$DATA_FILE -F, '
        {
            state_day_sum[$1 "," $2 "," $3 "," $4] = state_day_sum[$1 "," $2 "," $3 "," $4] + $5
            state_day_num[$1 "," $2 "," $3 "," $4] = state_day_num[$1 "," $2 "," $3 "," $4] + 1
        }
        END {
            for (state_day_key in state_day_sum) {
                print state_day_key "," state_day_sum[state_day_key]/state_day_num[state_day_key]
            }
        }
    ' OFS=, $DATA_FILE > STATE_DAY_${DATA_FILE}.tmp
    sort -k1 -k2 -k3 -k4 < STATE_DAY_${DATA_FILE}.tmp > STATE_DAY_$DATA_FILE
    rm -f STATE_DAY_${DATA_FILE}.tmp
done

以下是这些参数的含义

-F, 字段分隔符为 ,
FNR 每个文件中的行号
NR 两个文件中行号的总和
FNR==NR 仅在第一个文件 ${PATTERN_FILE} 中为 TRUE
{ x[$1]=$2; next; } 如果 FNR==NR 为 TRUE(仅适用于 $PATTERN_FILE 中的所有行)
- x 用于存储 station=state 映射的变量
- x[$1]=$2 station=state 的数据添加到映射
- $1 第一个文件中的第一列(站点代码)
- $2 第一个文件中的第二列(州代码)
- x 所有站点的映射,例如,x[US009052008]=SDx[US10RMHS145]=CO、...、x[USW00096409]=AK
- next 转到与 FNR==NR 匹配的下一行(本质上,这从 ${PATTERN_FILE} 创建所有站点状态的映射)
{ $1=x[$1]; print $0 } 如果 FNR==NR 为 FALSE(仅适用于 $DATA_FILE 中的所有行)
- $1=x[$1] 将第一个字段替换为 x[$1];本质上,将站点代码替换为州代码
- print $0 打印所有列(包括替换的 $1
OFS=, 输出字段分隔符为 ,

带有站点代码的 CSV

$ head TAVG_US_2010.csv
USR0000AALC,2010,01,01,-220
USR0000AALP,2010,01,01,-9
USR0000ABAN,2010,01,01,12
USR0000ABCA,2010,01,01,16
USR0000ABCK,2010,01,01,-309
USR0000ABER,2010,01,01,-81
USR0000ABEV,2010,01,01,-360
USR0000ABEN,2010,01,01,-224
USR0000ABNS,2010,01,01,89
USR0000ABLA,2010,01,01,59

运行命令

$ ./station_to_state_data.sh
TAVG_US_2010.csv
...
TAVG_US_2019.csv

站点现在已映射到州

$ head TAVG_US_2010.csv
AK,2010,01,01,-220
AZ,2010,01,01,-9
AL,2010,01,01,12
AK,2010,01,01,16
AK,2010,01,01,-309
AK,2010,01,01,-81
AK,2010,01,01,-360
AK,2010,01,01,-224
AZ,2010,01,01,59
AK,2010,01,01,-68

每个州每天都有多个温度读数,因此您需要计算每天每个州的读数的平均值。使用 AWK 进行文本处理,使用 sort 确保最终结果以逻辑顺序排列,并使用 rm 在处理后删除临时文件。

station_to_state_data.sh

PATTERN_FILE=us_stations.txt

for DATA_FILE in `ls TAVG_US_*.csv`
do
    echo ${DATA_FILE}

    awk -F, \
        'FNR==NR { x[$1]=$2; next; } { $1=x[$1]; print $0 }' \
        OFS=, \
        ${PATTERN_FILE} ${DATA_FILE} > ${DATA_FILE}.tmp

   mv ${DATA_FILE}.tmp ${DATA_FILE}
done

以下是 AWK 参数的含义

FILE=$DATA_FILE CSV 文件被处理为 FILE
-F, 字段分隔符为 ,
state_day_sum[$1 "," $2 "," $3 "," $4] = $5

state_day_sum[$1 "," $2 "," $3 "," $4] + $5
州($1)在年($2)、月($3)、日($4)的温度总和($5
state_day_num[$1 "," $2 "," $3 "," $4] = $5

state_day_num[$1 "," $2 "," $3 "," $4] + 1
州($1)在年($2)、月($3)、日($4)的温度读数数量
END 最后,在收集所有州、年、月、日的总和和读数数量之后,计算平均值
for (state_day_key in state_day_sum) 对于每个州年-月-日
print state_day_key "," state_day_sum[state_day_key]/state_day_num[state_day_key] 打印州、年、月、日、平均值
OFS=, 输出字段分隔符为 ,
$DATA_FILE 输入文件(一个接一个地以 TAVG_US_ 开头并以 .csv 结尾的所有文件)
> STATE_DAY_${DATA_FILE}.tmp 将结果保存到临时文件

运行脚本

$ ./TAVG_avg.sh
TAVG_US_2010.csv
TAVG_US_2011.csv
TAVG_US_2012.csv
TAVG_US_2013.csv
TAVG_US_2014.csv
TAVG_US_2015.csv
TAVG_US_2016.csv
TAVG_US_2017.csv
TAVG_US_2018.csv
TAVG_US_2019.csv

创建这些文件

$ ls STATE_DAY_TAVG_US_20*.csv
STATE_DAY_TAVG_US_2010.csv  STATE_DAY_TAVG_US_2015.csv
STATE_DAY_TAVG_US_2011.csv  STATE_DAY_TAVG_US_2016.csv
STATE_DAY_TAVG_US_2012.csv  STATE_DAY_TAVG_US_2017.csv
STATE_DAY_TAVG_US_2013.csv  STATE_DAY_TAVG_US_2018.csv
STATE_DAY_TAVG_US_2014.csv  STATE_DAY_TAVG_US_2019.csv

查看所有州的某一年数据(less 是一个实用程序,可以一次查看一页输出)

$ less STATE_DAY_TAVG_US_2010.csv
AK,2010,01,01,-181.934
...
AK,2010,01,31,-101.068
AK,2010,02,01,-107.11 
...
AK,2010,02,28,-138.834
...
WY,2010,01,01,-43.5625
...
WY,2010,12,31,-215.583

将所有数据文件合并为一个

$ cat STATE_DAY_TAVG_US_20*.csv > TAVG_US_2010-2019.csv

现在您有了一个文件,其中包含所有州、所有年份的数据

$ cat TAVG_US_2010-2019.csv
AK,2010,01,01,-181.934
...
WY,2018,12,31,-167.421
AK,2019,01,01,-32.3386
...
WY,2019,12,30,-131.028
WY,2019,12,31,-79.8704

4. 制作时间序列数据

像这样的问题很适合用时间序列模型来解决,例如长短期记忆网络(LSTM),它是一种循环神经网络(RNN)。输入数据被组织成时间切片;例如,将20天作为一个切片。

这是一个单独的时间切片(如STATE_DAY_TAVG_US_2010.csv)。

X (input – 20 weeks):
AK,2010,01,01,-181.934
AK,2010,01,02,-199.531
...
AK,2010,01,20,-157.273

y (21st week, prediction for these 20 weeks):
AK,2010,01,21,-165.31

该时间切片表示为(温度值,其中前20周为X,第21周为y)。

AK, -181.934,-199.531, ... ,
-157.273,-165.3

这些切片在时间上是连续的。 例如,2010年末延续到2011年。

AK,2010,12,22,-209.92
...
AK,2010,12,31,-79.8523
AK,2011,01,01,-59.5658
...
AK,2011,01,10,-100.623

这将产生以下预测:

AK,2011,01,11,-106.851

这个时间切片被认为是:

AK, -209.92, ... ,-79.8523,-59.5658, ... ,-100.623,-106.851

等等,针对所有州、年份、月份和日期。 更多解释请参阅关于时间序列预测的教程。

编写一个脚本来创建时间切片。

timeslices.sh

#!/bin/sh

TIME_SLICE_PERIOD=20

file=TAVG_US_2010-2019.csv

# For each state in file
for state in `cut -d',' -f1 $file | sort | uniq`
do
    # Get all temperature values for the state
    state_tavgs=`grep $state $file | cut -d',' -f5`
    # How many time slices will this result in?
    # mber of temperatures recorded minus size of one timeslice
    num_slices=`echo $state_tavgs | wc -w`
    num_slices=$((${num_slices} - ${TIME_SLICE_PERIOD}))
    # Initialize
    slice_start=1; num_slice=0;
    # For each timeslice
    while [ $num_slice -lt $num_slices ]
    do
        # One timeslice is from slice_start to slice_end
        slice_end=$(($slice_start + $TIME_SLICE_PERIOD - 1))
        # X (1-20)
        sliceX="$slice_start-$slice_end"
        # y (21)
        slicey=$(($slice_end + 1))
        # Print state and timeslice temperature values (column 1-20 and 21)
        echo $state `echo $state_tavgs | cut -d' ' -f$sliceX,$slicey`
        # Increment 
        slice_start=$(($slice_start + 1)); num_slice=$(($num_slice + 1));
    done
done

运行脚本。 它使用空格作为列分隔符;使用 sed 将它们更改为逗号。

$ ./timeslices.sh > TIMESLICE_TAVG_US_2010-2019.csv; sed -i s/' '/,/g TIME_VARIANT_TAVG_US_2010-2019.csv

以下是输出 .csv 文件的前几行和后几行。

$ head -3 TIME_VARIANT_TAVG_US_2009-2019.csv
AK,-271.271,-290.057,-300.324,-277.603,-270.36,-293.152,-292.829,-270.413,-256.674,-241.546,-217.757,-158.379,-102.585,-24.9517,-1.7973,15.9597,-5.78231,-33.932,-44.7655,-92.5694,-123.338
AK,-290.057,-300.324,-277.603,-270.36,-293.152,-292.829,-270.413,-256.674,-241.546,-217.757,-158.379,-102.585,-24.9517,-1.7973,15.9597,-5.78231,-33.932,-44.7655,-92.5694,-123.338,-130.829
AK,-300.324,-277.603,-270.36,-293.152,-292.829,-270.413,-256.674,-241.546,-217.757,-158.379,-102.585,-24.9517,-1.7973,15.9597,-5.78231,-33.932,-44.7655,-92.5694,-123.338,-130.829,-123.979

$ tail -3 TIME_VARIANT_TAVG_US_2009-2019.csv
WY,-76.9167,-66.2315,-45.1944,-27.75,-55.3426,-81.5556,-124.769,-137.556,-90.213,-54.1389,-55.9907,-30.9167,-9.59813,7.86916,-1.09259,-13.9722,-47.5648,-83.5234,-98.2963,-124.694,-142.898
WY,-66.2315,-45.1944,-27.75,-55.3426,-81.5556,-124.769,-137.556,-90.213,-54.1389,-55.9907,-30.9167,-9.59813,7.86916,-1.09259,-13.9722,-47.5648,-83.5234,-98.2963,-124.694,-142.898,-131.028
WY,-45.1944,-27.75,-55.3426,-81.5556,-124.769,-137.556,-90.213,-54.1389,-55.9907,-30.9167,-9.59813,7.86916,-1.09259,-13.9722,-47.5648,-83.5234,-98.2963,-124.694,-142.898,-131.028,-79.8704

虽然这确实有效,但效率不高。 可以对其进行优化——你能尝试一下吗? 在下面的评论中报告你是如何做的。

5. 创建训练、测试和验证数据集

将数据拆分为训练测试验证集。

data_sets.sh

#!/bin/sh

GEN=SEQ
# GEN=RAN

FILE=TIMESLICE_TAVG_US_2010-2019.csv

TRAIN_SET_PERCENT=70
TEST_SET_PERCENT=20
VAL_SET_PERCENT=$(( 100 - $TRAIN_SET_PERCENT - $TEST_SET_PERCENT ))

TRAIN_DATA=TRAIN_$FILE
TEST_DATA=TEST_$FILE
VAL_DATA=VAL_$FILE

> $TRAIN_DATA
> $TEST_DATA
> $VAL_DATA

for state in `cut -d',' -f1 $FILE | sort | uniq`
do
    NUM_STATE_DATA=`grep "$state" $FILE | wc -l`
    echo "$state: $NUM_STATE_DATA"

    TRAIN_NUM_DATA=$(( $NUM_STATE_DATA * $TRAIN_SET_PERCENT / 100 ))
    TEST_NUM_DATA=$(( $NUM_STATE_DATA * $TEST_SET_PERCENT / 100 ))
    VAL_NUM_DATA=$(( $NUM_STATE_DATA - $TRAIN_NUM_DATA - $TEST_NUM_DATA ))

    if [ $GEN == "SEQ" ]
    then
        echo "Sequential"
        STATE_DATA=`grep $state $FILE`
    elif [ $GEN == "RAN" ]
    then
        echo "Randomized"
        STATE_DATA=`grep $state $FILE | shuf`
    else
        echo "Unknown data gen type: " $GEN
        exit 1
    fi

    # Train set
    per=$TRAIN_SET_PERCENT
    num=$TRAIN_NUM_DATA; from=1; to=$(($from + $num - 1));
    echo Train set: $per% $num from=$from to=$to
    echo "$STATE_DATA" | head -$to >> $TRAIN_DATA

    # Test set
    per=$TEST_SET_PERCENT
    num=$TEST_NUM_DATA; from=$(($to + 1)); to=$(($from + $num - 1));
    echo Test set: $per% $num from=$from to=$to
    echo "$STATE_DATA" | head -$to | tail -$num >> $TEST_DATA

    # Validate set
    per=$VAL_SET_PERCENT
    num=$VAL_NUM_DATA; from=$(($to + 1)); to=$NUM_STATE_DATA;
    echo Validate set: $per% $num from=$from to=$to
    echo "$STATE_DATA" | tail -$num >> $VAL_DATA

    echo
done

这将生成数据集,可以通过在脚本中设置GEN=SEQGEN=RAN来顺序或随机化这些数据集,并且可以使用shuf来打乱数据。

运行脚本

$ ./data_sets.sh
AK: 3652
Sequential
Train set: 70% 2556 from=1 to=2556
Test set: 20% 730 from=2557 to=3286
Validate set: 10% 366 from=3287 to=3652

...

WY: 3352
Sequential
Train set: 70% 2346 from=1 to=2346
Test set: 20% 670 from=2347 to=3016
Validate set: 10% 336 from=3017 to=3352

要创建这些数据文件。

$ ls *_TIMESLICE_TAVG_US_2010-2019.csv
TEST_TIMESLICE_TAVG_US_2010-2019.csv   VAL_TIMESLICE_TAVG_US_2010-2019.csv
TRAIN_TIMESLICE_TAVG_US_2010-2019.csv

使用 shell 进行数据处理

当您需要为下一个机器学习项目处理大量数据时,请考虑 shell 命令和脚本。 它们经过验证,可以随时使用,并且有友好的社区来指导和帮助您。

本文介绍了用于数据处理的 shell,脚本展示了各种可能性。 还有更多可能。 您想继续深入研究吗? 在下面的评论中告诉我们。

接下来阅读什么
User profile image.
Girish 在印度一家全球 IT 服务组织拥有超过 20 年的技术和软件经验。 Girish 是 "I Got" 云平台的架构师,该平台旨在通过开源堆栈和现代架构模式(例如微服务、容器化和多租户)来提升金字塔底部。 Girish 撰写有关开源和技术主题的文章。

3 条评论

感谢 Girish 撰写的这篇有趣的指南。 遗憾的是,TAVG_avg.sh 的列表丢失了。 相反,您两次列出了上一个脚本

是的。 已经注意到并且通知编辑进行修复。 请刷新缓存,现在应该可见了。

Creative Commons License本作品采用知识共享署名-相同方式共享 4.0 国际许可协议授权。
© . All rights reserved.