บทนำ
Machine learning เป็นความสามารถคอมพิวติ้งที่ทรงพลังสำหรับการพยากรณ์หรือ forecasting สิ่งต่างๆ ที่ conventional algorithms พบว่าท้าทาย การเดินทางของ machine learning เริ่มต้นด้วยการเก็บและเตรียมข้อมูล — เยอะมาก — แล้วสร้าง mathematical models จากข้อมูลนั้น แม้จะมีหลายเครื่องมือสำหรับงานเหล่านี้ ผมชอบใช้ shell
Shell เป็นอินเทอร์เฟซสำหรับดำเนินการโดยใช้ภาษาที่กำหนด ภาษานี้สามารถเรียกใช้แบบ interactive หรือ scripted แนวคิด shell ถูกนำเสนอใน Unix operating systems ในทศวรรษ 1970 Shells ยอดนิยมรวมถึง Bash, tcsh, และ Zsh พวกมันพร้อมสำหรับทุกระบบปฏิบัติการ รวมถึง Linux, macOS, และ Windows ทำให้มี portability สูง สำหรับแบบฝึกหัดนี้ ผมจะใช้ Bash
บทความนี้เป็นการแนะนำการใช้ shell สำหรับการเก็บข้อมูลและเตรียมข้อมูล ไม่ว่าคุณจะเป็น data scientist ที่มองหาเครื่องมือที่มีประสิทธิภาพ หรือ shell expert ที่มองใช้ทักษะสำหรับ machine learning ผมหวังว่าคุณจะพบข้อมูลที่มีค่า
ปัญหาตัวอย่างในบทความนี้คือการสร้าง machine learning model เพื่อพยากรณ์อุณหภูมิของรัฐใน US ใช้ shell commands และ scripts ทำขั้นตอนการเก็บและเตรียมข้อมูลต่อไปนี้:
- ดาวน์โหลดข้อมูล
- แยกฟิลด์ที่จำเป็น
- รวมข้อมูล (Aggregate)
- สร้าง time series
- สร้าง train, test, และ validate data sets
คุณอาจถามว่าทำไมต้องทำด้วย shell ถ้าทำได้หมดใน machine learning programming language อย่าง Python คำถามที่ดี หาก data processing ทำด้วยเทคโนโลยีที่ง่าย เรียบง่าย และรวย เช่น shell data scientist จะโฟกัสแค่ machine learning modeling ไม่ใช่รายละเอียดของภาษา
ข้อกำหนดเบื้องต้น
ก่อนอื่น คุณต้องมี shell interpreter ติดตั้ง หากคุณใช้ Linux หรือ macOS มันจะติดตั้งอยู่แล้ว และคุณอาจคุ้นเคยแล้ว หากใช้ Windows ลอง MinGW หรือ Cygwin
สำหรับข้อมูลเพิ่มเติม ดู:
- Bash tutorials บน opensource.com
- Official shell scripting tutorial โดย Steve Parker ผู้สร้าง Bourne shell
- The Bash Guide for Beginners โดย Linux Documentation Project
- หากต้องการช่วยเหลือคำสั่งเฉพาะ พิมพ์
<commandname> --helpใน shell เช่นls --help
เริ่มต้น
ตอนนี้ shell ของคุณพร้อมแล้ว คุณสามารถเริ่มเตรียมข้อมูลสำหรับปัญหา machine learning พยากรณ์อุณหภูมิ
1. ดาวน์โหลดข้อมูล
ข้อมูลสำหรับ tutorial นี้มาจาก US National Oceanic and Atmospheric Administration (NOAA) คุณจะ train model ด้วยข้อมูล 10 ปีเต็มล่าสุด Data source อยู่ที่ https://www1.ncdc.noaa.gov/pub/data/ghcn/daily/by_year/ และข้อมูลเป็นรูปแบบ .csv และ gzipped
ดาวน์โหลดและ unzip ข้อมูลด้วย shell script ใช้ text editor โปรดสร้างไฟล์ชื่อ 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
Notes:
- หากคุณอยู่หลัง proxy server โปรดดู how-to ของ Mark Grennan และใช้:
export http_proxy=https://username:password@proxyhost:port/ export https_proxy=https://username:password@proxyhost:port/
- ตรวจสอบว่า standard commands ทั้งหมดอยู่ใน PATH แล้ว (เช่น
/binหรือ/usr/bin) หากไม่ได้ ตั้ง PATH - Wget เป็น utility สำหรับเชื่อมต่อ web servers จากบรรทัดคำสั่ง หาก Wget ไม่ได้ติดตั้ง ดาวน์โหลดมัน
- ตรวจสอบว่ามี gzip utility สำหรับ compression และ decompression
รันสคริปต์นี้เพื่อดาวน์โหลด แยกไฟล์ และทำให้ข้อมูล 10 ปีพร้อมเป็น CSVs:
$ ./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. แยกอุณหภูมิเฉลี่ย
แยกข้อมูล TAVG (average temperature) จาก CSVs สำหรับภูมิภาค US:
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 เป็น utility สำหรับแสดงบรรทัดแรกๆ (โดยค่าเริ่มต้น 10 บรรทัด) ของไฟล์
ข้อมูลมีข้อมูลมากกว่าที่คุณต้องการ จำกัดจำนวนคอลัมน์โดยกำจัดคอลัมน์ 3 (เพราะข้อมูลทั้งหมดคือ average temperature) และคอลัมน์ 5 เป็นต้นไป กล่าวคือ เก็บคอลัมน์ 1 (climate station), 2 (date), และ 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
วันที่อยู่ในรูปแบบ string (YMD) เพื่อ train model ให้ถูกต้อง algorithms ของคุณต้องรู้จัก date fields ในรูปแบบ Y,M,D คั่นด้วย comma (เช่น 20100101 กลายเป็น 2010,01,01) คุณแปลงได้ด้วย sed utility
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. รวมข้อมูลอุณหภูมิเฉลี่ยของรัฐ
ข้อมูลสภาพอากาศมาจาก climate stations ในเมือง US แต่คุณต้องการพยากรณ์อุณหภูมิของทั้งรัฐ ในการแปลงข้อมูล climate-station เป็นข้อมูลรัฐ แรกเริ่ม map climate stations ไปยังรัฐของพวกมัน
ดาวน์โหลดรายชื่อ climate stations ด้วย wget:
$ wget ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/daily/ghcnd-stations.txt
แยก US stations ด้วย grep utility เพื่อหา US listings คำสั่งต่อไปนี้ค้นหาบรรทัดที่ขึ้นต้นด้วยข้อความ "US > เป็น redirection ที่เขียน output ไปไฟล์ — ในกรณีนี้ ไฟล์ชื่อ us_stations.txt:
$ grep "^US" ghcnd-stations.txt > us_stations.txt
ไฟล์นี้สร้างสำหรับ pretty print ดังนั้น column separators ไม่สม่ำเสมอ:
$ 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 squeeze repeats และ output ไป temp file และ rename temp file กลับเป็น original — ทั้งหมดในบรรทัดเดียว:
$ cat us_stations.txt | tr -s ' ' > us_stations.txt.tmp; cp us_stations.txt.tmp us_stations.txt;
บรรทัดแรกของ output คำสั่ง:
$ 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 coordinates และอื่นๆ — แต่คุณต้องการแค่ station code และ state ใช้ cut:
$ cut -d' ' -f1,5 us_stations.txt > us_stations.txt.tmp; mv us_stations.txt.tmp us_stations.txt;
บรรทัดแรกของ output คำสั่ง:
$ head us_stations.txt US009052008 SD US10RMHS145 CO US10adam001 NE US10adam002 NE ...
ทำให้เป็น CSV และเปลี่ยน space เป็น comma separators ด้วย sed:
$ sed -i s/' '/,/g us_stations.txt
บรรทัดแรกของ output คำสั่ง:
$ head us_stations.txt US009052008,SD US10RMHS145,CO US10adam001,NE US10adam002,NE ...
แม้คุณจะใช้คำสั่งหลายตัวสำหรับงานเหล่านี้ แต่มันเป็นไปได้ที่จะทำทุกขั้นตอนใน one run ลองทำเองดู
ตอนนี้ แทนที่ station codes ด้วย state locations โดยใช้ AWK ซึ่งมีประสิทธิภาพสูงสำหรับ large data processing
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, | Field separator คือ , |
FNR | Line number ในแต่ละไฟล์ |
NR | Line number ในทั้งสองไฟล์รวมกัน |
FNR==NR | เป็น TRUE เฉพาะในไฟล์แรก ${PATTERN_FILE} |
{ x[$1]=$2; next; } | ถ้า FNR==NR เป็น TRUE (สำหรับทุกบรรทัดใน $PATTERN_FILE เท่านั้น) |
- x | Variable เก็บ map station=state |
- x[$1]=$2 | เพิ่มข้อมูล station=state ลง map |
- $1 | คอลัมน์แรกในไฟล์แรก (station codes) |
- $2 | คอลัมน์ที่สองในไฟล์แรก (state codes) |
- x | Map ของทุก stations เช่น x[US009052008]=SD, x[US10RMHS145]=CO, ..., x[USW00096409]=AK |
- next | ไปบรรทัดถัดไปที่ match FNR==NR (โดยสรุป สร้าง map ของ stations-states ทั้งหมดจาก ${PATTERN_FILE} |
{ $1=x[$1]; print $0 } | ถ้า FNR==NR เป็น FALSE (สำหรับทุกบรรทัด in $DATA_FILE เท่านั้น) |
- $1=x[$1] | แทนที่ฟิลด์แรกด้วย x[$1]; กล่าวคือ แทนที่ station code ด้วย state code |
- print $0 | พิมพ์ทุกคอลัมน์ (รวม $1 ที่แทนที่แล้ว) |
OFS=, | Output fields separator คือ , |
CSV ที่มี station codes:
$ 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
Stations ตอนนี้ mapped ไป states แล้ว:
$ 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 สำหรับ text processing, sort เพื่อให้ผลลัพธ์สุดท้ายเรียงลำดับสมเหตุสมผล และ rm เพื่อลบ temporary file หลังประมวลผล
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 parameters:
FILE=$DATA_FILE | CSV file processed as FILE |
-F, | Field separator คือ , |
state_day_sum[$1 "," $2 "," $3 "," $4] = $5 | Sum of temperature ($5) for the state ($1) on year ($2), month ($3), day ($4) |
state_day_num[$1 "," $2 "," $3 "," $4] = $5 | Number of temperature readings for the state ($1) on year ($2), month ($3), day ($4) |
END | ในท้ายที่สุด หลังจากรวบรวม sum และจำนวน readings สำหรับทุกรัฐ ปี เดือน วัน คำนวณ averages |
for (state_day_key in state_day_sum) | สำหรับแต่ละ state-year-month-day |
print state_day_key "," state_day_sum[state_day_key]/state_day_num[state_day_key] | พิมพ์ state,year,month,day,average |
OFS=, | Output fields separator คือ , |
$DATA_FILE | Input file (all files with name starting with TAVG_US_ and ending with .csv, one by one) |
> STATE_DAY_${DATA_FILE}.tmp | Save result to a temporary file |
รันสคริปต์:
$ ./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 คือ utility ดู output ทีละหน้า):
$ 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. สร้างข้อมูล Time-series
ปัญหาแบบนี้เหมาะกับ time-series model อย่าง long short-term memory (LSTM) ซึ่งเป็น recurring neural network (RNN) Input data จัดเป็น time slices พิจารณา 20 วันเป็นหนึ่ง slice
นี่คือ one-time slice (จาก 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
Time slice นี้แสดงเป็น (ค่าอุณหภูมิที่ 20 สัปดาห์แรกคือ X, และ 21 คือ y):
AK, -181.934,-199.531, ... , -157.273,-165.3
Slices เป็น time-contiguous ตัวอย่าง สิ้นสุด 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
ซึ่งให้ prediction:
AK,2011,01,11,-106.851
Time slice นี้ถูกนำเป็น:
AK, -209.92, ... ,-79.8523,-59.5658, ... ,-100.623,-106.851
และต่อเนื่องไป สำหรับทุกรัฐ ปี เดือน และวันที่ สำหรับคำอธิบายเพิ่มเติม ดู tutorial on time-series forecasting
เขียนสคริปต์สร้าง time slices:
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
รันสคริปต์ มันใช้ space เป็น column separators ทำให้เป็น comma ด้วย sed:
$ ./timeslices.sh > TIMESLICE_TAVG_US_2010-2019.csv; sed -i s/' '/,/g TIME_VARIANT_TAVG_US_2010-2019.csv
นี่คือบรรทัดแรกๆ และบรรทัดสุดท้ายของ output .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
แม้จะทำงานได้ แต่มันไม่ค่อย performant สามารถ optimize ได้ — คุณลองดูได้ไหม รายงานในความคิดเห็นด้านล่างว่าคุณทำอย่างไร
5. สร้าง train, test, และ validate data sets
แยกข้อมูลเป็น train, test, และ validate sets
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
สคริปต์นี้สร้าง data sets ที่เป็น sequential หรือ randomized โดยตั้ง GEN=SEQ หรือ GEN=RAN ในสคริปต์ และคุณสามารถ shuffle data ด้วย 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
เมื่อคุณต้องประมวลผลข้อมูลจำนวนมหาศาลสำหรับ machine learning project ถัดไป ลองคิดถึง shell commands และ scripts มันพิสูจน์แล้วและพร้อมใช้งานพร้อมชุมชนที่เป็นมิตรช่วยเหลือและนำทางคุณ
บทความนี้แนะนำ shell สำหรับ data processing และสคริปต์สาธิตโอกาส มากกว่านี้ก็ทำได้อีกมาก อยากพัฒนาต่อไหม? บอกเราในความคิดเห็นด้านล่าง