使用 Bash 创建机器学习模型

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

Opensource.com

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

shell 是使用定义的语言执行操作的界面。这种语言可以交互式调用或编写脚本。Unix 操作系统在 1970 年代引入了 shell 的概念。一些最流行的 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 中键入 <commandname> --help 以获取帮助;例如:ls --help

开始

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

1. 下载数据

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

使用 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 作为 FILE 处理的 CSV 文件
-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)),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 的列表丢失了。相反,您列出了之前的脚本两次

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

© . All rights reserved.