Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม BASH

สร้างโมเดลแมชชีนเลิร์นนิงด้วย Bash

แมชชีนเลิร์นนิงคือความสามารถในการคำนวณที่ทรงพลังสำหรับการทำนายหรือคาดการณ์สิ่งต่าง ๆ ที่อัลกอริธึมทั่วไปพบว่ามีความท้าทาย เส้นทางการเรียนรู้ของเครื่องเริ่มต้นด้วยการรวบรวมและเตรียมข้อมูล—ล็อต ของมัน—จากนั้นก็สร้างแบบจำลองทางคณิตศาสตร์ตามข้อมูลนั้น แม้ว่าเครื่องมือต่างๆ จะใช้สำหรับงานเหล่านี้ได้ แต่ฉันชอบที่จะใช้เชลล์

เชลล์เป็นส่วนต่อประสานสำหรับการดำเนินการโดยใช้ภาษาที่กำหนด ภาษานี้สามารถเรียกใช้แบบโต้ตอบหรือเขียนสคริปต์ได้ แนวคิดของเชลล์ถูกนำมาใช้ในระบบปฏิบัติการ Unix ในปี 1970 เชลล์ยอดนิยมบางตัว ได้แก่ Bash, tcsh และ Zsh ใช้ได้กับทุกระบบปฏิบัติการ รวมถึง Linux, macOS และ Windows ซึ่งช่วยให้พกพาได้สะดวก สำหรับแบบฝึกหัดนี้ ฉันจะใช้ Bash

บทความนี้เป็นการแนะนำการใช้เชลล์ในการรวบรวมข้อมูลและการเตรียมข้อมูล ไม่ว่าคุณจะเป็นนักวิทยาศาสตร์ข้อมูลที่กำลังมองหาเครื่องมือที่มีประสิทธิภาพหรือผู้เชี่ยวชาญด้านเชลล์ที่ต้องการใช้ทักษะของคุณในการเรียนรู้ของเครื่อง เราหวังว่าคุณจะพบข้อมูลที่มีค่าที่นี่

ปัญหาตัวอย่างในบทความนี้คือการสร้างแบบจำลองการเรียนรู้ของเครื่องเพื่อคาดการณ์อุณหภูมิสำหรับรัฐในสหรัฐอเมริกา มันใช้คำสั่งเชลล์และสคริปต์เพื่อทำการรวบรวมข้อมูลและขั้นตอนการจัดเตรียมข้อมูลต่อไปนี้:

  1. ดาวน์โหลดข้อมูล
  2. แยกฟิลด์ที่จำเป็น
  3. ข้อมูลรวม
  4. สร้างอนุกรมเวลา
  5. สร้างการฝึก ทดสอบ และตรวจสอบชุดข้อมูล

คุณอาจจะถามว่าทำไมคุณควรทำสิ่งนี้กับเชลล์ ในเมื่อคุณสามารถทำได้ทั้งหมดในภาษาโปรแกรมการเรียนรู้ของเครื่อง เช่น 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

state_day_sum[$1 "," $2 "," $3 "," $4] + $5
ผลรวมของอุณหภูมิ ($5 ) สำหรับสถานะ ($1 ) ในปี ($2 ) เดือน ($3 ) วัน ($4 )
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 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

การประมวลผลข้อมูลด้วยเชลล์

เมื่อคุณต้องการประมวลผลข้อมูลจำนวนมหาศาลสำหรับโปรเจ็กต์แมชชีนเลิร์นนิงครั้งต่อไปของคุณ ให้นึกถึงคำสั่งเชลล์และสคริปต์ ได้รับการพิสูจน์และพร้อมที่จะใช้กับชุมชนที่เป็นมิตรเพื่อเป็นแนวทางและช่วยเหลือคุณ

บทความนี้จะแนะนำเชลล์สำหรับการประมวลผลข้อมูล และสคริปต์แสดงโอกาสต่างๆ เป็นไปได้มากขึ้น คุณต้องการที่จะนำมันไปข้างหน้า? บอกเราในความคิดเห็นด้านล่าง