แมชชีนเลิร์นนิงคือความสามารถในการคำนวณที่ทรงพลังสำหรับการทำนายหรือคาดการณ์สิ่งต่าง ๆ ที่อัลกอริธึมทั่วไปพบว่ามีความท้าทาย เส้นทางการเรียนรู้ของเครื่องเริ่มต้นด้วยการรวบรวมและเตรียมข้อมูล—ล็อต ของมัน—จากนั้นก็สร้างแบบจำลองทางคณิตศาสตร์ตามข้อมูลนั้น แม้ว่าเครื่องมือต่างๆ จะใช้สำหรับงานเหล่านี้ได้ แต่ฉันชอบที่จะใช้เชลล์
เชลล์เป็นส่วนต่อประสานสำหรับการดำเนินการโดยใช้ภาษาที่กำหนด ภาษานี้สามารถเรียกใช้แบบโต้ตอบหรือเขียนสคริปต์ได้ แนวคิดของเชลล์ถูกนำมาใช้ในระบบปฏิบัติการ Unix ในปี 1970 เชลล์ยอดนิยมบางตัว ได้แก่ Bash, tcsh และ Zsh ใช้ได้กับทุกระบบปฏิบัติการ รวมถึง Linux, macOS และ Windows ซึ่งช่วยให้พกพาได้สะดวก สำหรับแบบฝึกหัดนี้ ฉันจะใช้ Bash
บทความนี้เป็นการแนะนำการใช้เชลล์ในการรวบรวมข้อมูลและการเตรียมข้อมูล ไม่ว่าคุณจะเป็นนักวิทยาศาสตร์ข้อมูลที่กำลังมองหาเครื่องมือที่มีประสิทธิภาพหรือผู้เชี่ยวชาญด้านเชลล์ที่ต้องการใช้ทักษะของคุณในการเรียนรู้ของเครื่อง เราหวังว่าคุณจะพบข้อมูลที่มีค่าที่นี่
ปัญหาตัวอย่างในบทความนี้คือการสร้างแบบจำลองการเรียนรู้ของเครื่องเพื่อคาดการณ์อุณหภูมิสำหรับรัฐในสหรัฐอเมริกา มันใช้คำสั่งเชลล์และสคริปต์เพื่อทำการรวบรวมข้อมูลและขั้นตอนการจัดเตรียมข้อมูลต่อไปนี้:
- ดาวน์โหลดข้อมูล
- แยกฟิลด์ที่จำเป็น
- ข้อมูลรวม
- สร้างอนุกรมเวลา
- สร้างการฝึก ทดสอบ และตรวจสอบชุดข้อมูล
คุณอาจจะถามว่าทำไมคุณควรทำสิ่งนี้กับเชลล์ ในเมื่อคุณสามารถทำได้ทั้งหมดในภาษาโปรแกรมการเรียนรู้ของเครื่อง เช่น Python นี่เป็นคำถามที่ดี หากประมวลผลข้อมูลด้วยเทคโนโลยีที่ใช้งานง่าย เป็นมิตร และสมบูรณ์ เช่น เชลล์ นักวิทยาศาสตร์ข้อมูลจะมุ่งเน้นที่การสร้างแบบจำลองแมชชีนเลิร์นนิงเท่านั้น ไม่ใช่รายละเอียดของภาษา
ข้อกำหนดเบื้องต้น
ก่อนอื่น คุณต้องติดตั้งตัวแปลเชลล์ก่อน หากคุณใช้ Linux หรือ macOS จะมีการติดตั้งไว้แล้ว และคุณอาจคุ้นเคยกับมันอยู่แล้ว หากคุณใช้ Windows ให้ลองใช้ MinGW หรือ Cygwin
สำหรับข้อมูลเพิ่มเติม โปรดดู:
- สอน Bash ที่นี่บน opensource.com
- บทแนะนำการเขียนสคริปต์เชลล์อย่างเป็นทางการโดย Steve Parker ผู้สร้าง Bourne shell
- Bash Guide for Beginners โดย Linux Documentation Project
- หากต้องการความช่วยเหลือเกี่ยวกับคำสั่งเฉพาะ ให้พิมพ์
<commandname> --help
ในเปลือกเพื่อขอความช่วยเหลือ ตัวอย่างเช่น:ls --help
.
เริ่มต้นใช้งาน
เมื่อตั้งค่าเชลล์เรียบร้อยแล้ว คุณก็เริ่มเตรียมข้อมูลสำหรับปัญหาการทำนายอุณหภูมิของแมชชีนเลิร์นนิงได้
1. ดาวน์โหลดข้อมูล
ข้อมูลสำหรับบทช่วยสอนนี้มาจาก US National Oceanic and Atmospheric Administration (NOAA) คุณจะฝึกโมเดลของคุณโดยใช้ข้อมูล 10 ปีที่ผ่านมาที่สมบูรณ์ แหล่งข้อมูลอยู่ที่ https://www1.ncdc.noaa.gov/pub/data/ghcn/daily/by_year/ และข้อมูลอยู่ในรูปแบบ .csv และ gzipped
ดาวน์โหลดและคลายซิปข้อมูลโดยใช้เชลล์สคริปต์ ใช้โปรแกรมแก้ไขข้อความที่คุณชื่นชอบเพื่อสร้างไฟล์ชื่อ 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=https://username:password@proxyhost:port/
export https_proxy=https://username:password@proxyhost:port/ - ตรวจสอบให้แน่ใจว่าคำสั่งมาตรฐานทั้งหมดอยู่ใน PATH ของคุณแล้ว (เช่น
/bin
หรือ/usr/bin
). ถ้าไม่ ให้ตั้งค่า PATH ของคุณ - Wget เป็นยูทิลิตี้สำหรับการเชื่อมต่อกับเว็บเซิร์ฟเวอร์จากบรรทัดคำสั่ง หากไม่ได้ติดตั้ง 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. ดึงอุณหภูมิเฉลี่ย
ดึงข้อมูล TAVG (อุณหภูมิเฉลี่ย) จาก CSV สำหรับภูมิภาคในสหรัฐอเมริกา:
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 เพื่อบีบการทำซ้ำและส่งออกไปยังไฟล์ temp และเปลี่ยนชื่อไฟล์ temp กลับเป็นต้นฉบับ ทั้งหมดในบรรทัดเดียว:
$ 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 -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 ซึ่งมีประสิทธิภาพสูงสำหรับการประมวลผลข้อมูลขนาดใหญ่
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} |
{ x[$1]=$2; next; } | ถ้า FNR==NR เป็น TRUE (สำหรับทุกบรรทัดใน $PATTERN_FILE เท่านั้น) |
- x | ตัวแปรในการจัดเก็บ station=state แผนที่ |
- x[$1]=$2 | เพิ่มข้อมูลของ station=state ไปที่แผนที่ |
- $1 | คอลัมน์แรกในไฟล์แรก (รหัสสถานี) |
- $2 | คอลัมน์ที่สองในไฟล์แรก (รหัสสถานะ) |
- x | แผนที่สถานีทั้งหมด เช่น x[US009052008]=SD , x[US10RMHS145]=CO , ..., x[USW00096409]=AK |
- next | ไปที่การจับคู่บรรทัดถัดไป FNR==NR (โดยพื้นฐานแล้ว สิ่งนี้จะสร้างแผนที่ของสถานะสถานีทั้งหมดจาก ${PATTERN_FILE} |
{ $1=x[$1]; print $0 } | ถ้า FNR==NR เป็น FALSE (สำหรับทุกบรรทัด in $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 สำหรับการประมวลผลข้อความ จัดเรียงเพื่อให้แน่ใจว่าผลลัพธ์สุดท้ายอยู่ในลำดับเชิงตรรกะ และ 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 | ผลรวมของอุณหภูมิ ($5 ) สำหรับสถานะ ($1 ) ในปี ($2 ) เดือน ($3 ) วัน ($4 ) |
state_day_num[$1 "," $2 "," $3 "," $4] = $5 | จำนวนการอ่านอุณหภูมิสำหรับรัฐ ($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 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. สร้างการฝึกอบรม ทดสอบ และตรวจสอบชุดข้อมูล
แยกข้อมูลออกเป็น train , ทดสอบ และ ตรวจสอบ ชุด
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=SEQ
หรือ GEN=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
การประมวลผลข้อมูลด้วยเชลล์
เมื่อคุณต้องการประมวลผลข้อมูลจำนวนมหาศาลสำหรับโปรเจ็กต์แมชชีนเลิร์นนิงครั้งต่อไปของคุณ ให้นึกถึงคำสั่งเชลล์และสคริปต์ ได้รับการพิสูจน์และพร้อมที่จะใช้กับชุมชนที่เป็นมิตรเพื่อเป็นแนวทางและช่วยเหลือคุณ
บทความนี้จะแนะนำเชลล์สำหรับการประมวลผลข้อมูล และสคริปต์แสดงโอกาสต่างๆ เป็นไปได้มากขึ้น คุณต้องการที่จะนำมันไปข้างหน้า? บอกเราในความคิดเห็นด้านล่าง