Computer >> Máy Tính >  >> Lập trình >> Lập trình BASH

Tạo mô hình học máy với Bash

Máy học là một khả năng tính toán mạnh mẽ để dự đoán hoặc dự báo những điều mà các thuật toán thông thường thấy khó khăn. Hành trình học máy bắt đầu với việc thu thập và chuẩn bị dữ liệu — một của nó — sau đó nó xây dựng các mô hình toán học dựa trên dữ liệu đó. Mặc dù có thể sử dụng nhiều công cụ cho những tác vụ này, nhưng tôi thích sử dụng shell.

Một trình bao là một giao diện để thực hiện các hoạt động sử dụng một ngôn ngữ xác định. Ngôn ngữ này có thể được gọi tương tác hoặc theo tập lệnh. Khái niệm shell được giới thiệu trong hệ điều hành Unix vào những năm 1970. Một số shell phổ biến nhất bao gồm Bash, tcsh và Zsh. Chúng có sẵn cho tất cả các hệ điều hành, bao gồm Linux, macOS và Windows, mang lại cho chúng tính di động cao. Đối với bài tập này, tôi sẽ sử dụng Bash.

Bài viết này giới thiệu cách sử dụng shell để thu thập dữ liệu và chuẩn bị dữ liệu. Cho dù bạn là một nhà khoa học dữ liệu đang tìm kiếm các công cụ hiệu quả hay một chuyên gia trình bao đang tìm cách sử dụng các kỹ năng của bạn để học máy, tôi hy vọng bạn sẽ tìm thấy thông tin có giá trị ở đây.

Vấn đề ví dụ trong bài viết này là tạo ra một mô hình học máy để dự báo nhiệt độ cho các bang của Hoa Kỳ. Nó sử dụng các lệnh và tập lệnh shell để thực hiện các bước thu thập dữ liệu và chuẩn bị dữ liệu sau:

  1. Tải xuống dữ liệu
  2. Trích xuất các trường cần thiết
  3. Dữ liệu tổng hợp
  4. Tạo chuỗi thời gian
  5. Tạo tập, kiểm tra và xác thực các tập dữ liệu

Bạn có thể hỏi tại sao bạn nên làm điều này với shell, khi bạn có thể thực hiện tất cả bằng ngôn ngữ lập trình học máy như Python. Đây là một câu hỏi hay. Nếu việc xử lý dữ liệu được thực hiện bằng một công nghệ dễ dàng, thân thiện và phong phú như shell, thì nhà khoa học dữ liệu chỉ tập trung vào mô hình học máy chứ không phải chi tiết của một ngôn ngữ.

Điều kiện tiên quyết

Đầu tiên, bạn cần phải cài đặt trình thông dịch shell. Nếu bạn sử dụng Linux hoặc macOS, nó sẽ được cài đặt sẵn và bạn có thể đã quen với nó. Nếu bạn sử dụng Windows, hãy thử MinGW hoặc Cygwin.

Để biết thêm thông tin, hãy xem:

  • Các bài hướng dẫn về Bash tại đây trên opensource.com
  • Hướng dẫn viết kịch bản shell chính thức của Steve Parker, tác giả của Bourne shell
  • Hướng dẫn Bash cho người mới bắt đầu của Dự án Tài liệu Linux
  • Nếu bạn cần trợ giúp với một lệnh cụ thể, hãy nhập <commandname> --help trong vỏ để được giúp đỡ; ví dụ:ls --help .

Bắt đầu

Bây giờ shell của bạn đã được thiết lập, bạn có thể bắt đầu chuẩn bị dữ liệu cho bài toán dự đoán nhiệt độ của máy học.

1. Tải xuống dữ liệu

Dữ liệu cho hướng dẫn này đến từ Cơ quan Khí quyển và Đại dương Quốc gia Hoa Kỳ (NOAA). Bạn sẽ đào tạo mô hình của mình bằng cách sử dụng dữ liệu hoàn chỉnh của 10 năm qua. Nguồn dữ liệu tại https://www1.ncdc.noaa.gov/pub/data/ghcn/daily/by_year/ và dữ liệu ở định dạng .csv và được nén.

Tải xuống và giải nén dữ liệu bằng tập lệnh shell. Sử dụng trình soạn thảo văn bản yêu thích của bạn để tạo tệp có tên download.sh và dán mã bên dưới. Các nhận xét trong mã giải thích chức năng của các lệnh:

#!/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

Ghi chú:

  • Nếu bạn đang sử dụng máy chủ proxy, hãy tham khảo cách thực hiện của Mark Grennan và sử dụng:
    export http_proxy=https://username:password@proxyhost:port/
    export https_proxy=https://username:password@proxyhost:port/
  • Đảm bảo rằng tất cả các lệnh chuẩn đã có trong PATH của bạn (chẳng hạn như /bin hoặc /usr/bin ). Nếu không, hãy đặt PATH của bạn.
  • Wget là một tiện ích để kết nối với các máy chủ web từ dòng lệnh. Nếu Wget chưa được cài đặt trên hệ thống của bạn, hãy tải xuống.
  • Đảm bảo bạn có gzip, một tiện ích dùng để nén và giải nén.

Chạy tập lệnh này để tải xuống, trích xuất và cung cấp dữ liệu có giá trị 10 năm dưới dạng 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

...

Lệnh ls liệt kê nội dung của một thư mục. Sử dụng ls 20*.csv để liệt kê tất cả các tệp của bạn có tên bắt đầu bằng 20 và kết thúc bằng .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. Trích xuất nhiệt độ trung bình

Trích xuất dữ liệu TAVG (nhiệt độ trung bình) từ CSV cho các vùng của Hoa Kỳ:

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

Tập lệnh này:

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

tạo các tệp này:

$ 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

Đây là vài dòng đầu tiên cho 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,

Lệnh head là một tiện ích để hiển thị một số dòng đầu tiên (theo mặc định là 10 dòng) của tệp.

Dữ liệu có nhiều thông tin hơn bạn cần. Giới hạn số lượng cột bằng cách loại bỏ cột 3 (vì tất cả dữ liệu là nhiệt độ trung bình) và cột 5 trở đi. Nói cách khác, giữ các cột 1 (trạm khí hậu), 2 (ngày tháng) và 4 (ghi nhiệt độ).

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

Chạy tập lệnh:

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

Vài dòng đầu tiên của TAVG_US_2010.csv với dữ liệu không cần thiết bị xóa là:

$ 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

Ngày ở dạng chuỗi (YMD). Để đào tạo mô hình của bạn một cách chính xác, các thuật toán của bạn cần nhận ra các trường ngày trong biểu mẫu Y, M, D được phân tách bằng dấu phẩy (Ví dụ:20100101 trở thành 2010,01,01 ). Bạn có thể chuyển đổi chúng bằng tiện ích 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

Chạy tập lệnh:

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

Vài dòng đầu tiên của TAVG_US_2010.csv với định dạng ngày được phân tách bằng dấu phẩy là:

$ 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. Tổng hợp dữ liệu nhiệt độ trung bình của các tiểu bang

Dữ liệu thời tiết đến từ các trạm khí hậu đặt tại các thành phố của Hoa Kỳ, nhưng bạn muốn dự báo nhiệt độ của toàn tiểu bang. Để chuyển đổi dữ liệu trạm khí hậu thành dữ liệu trạng thái, trước tiên, hãy lập bản đồ các trạm khí hậu với trạng thái của chúng.

Tải xuống danh sách các trạm khí hậu bằng cách sử dụng wget:

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

Trích xuất các đài của Hoa Kỳ với tiện ích grep để tìm danh sách của Hoa Kỳ. Lệnh sau tìm kiếm các dòng bắt đầu bằng văn bản "US . "> là chuyển hướng ghi đầu ra vào một tệp — trong trường hợp này là vào tệp có tên us_stations.txt :

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

Tệp này được tạo cho bản in đẹp, vì vậy các dấu phân tách cột không nhất quán:

$ 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
...

Làm cho chúng nhất quán bằng cách sử dụng cat để in tệp, sử dụng tr để ép các lần lặp lại và xuất ra tệp tạm thời, đồng thời đổi tên tệp tạm trở lại như ban đầu — tất cả trong một dòng:

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

Các dòng đầu tiên của đầu ra của lệnh:

$ 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
...

Điều này chứa rất nhiều thông tin — tọa độ GPS và những thứ khác — nhưng bạn chỉ cần mã trạm và trạng thái. Sử dụng cắt:

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

Các dòng đầu tiên của đầu ra của lệnh:

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

Đặt đây là CSV và thay đổi khoảng trắng thành dấu phân cách bằng dấu phẩy bằng cách sử dụng sed:

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

Các dòng đầu tiên của đầu ra của lệnh:

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

Mặc dù bạn đã sử dụng một số lệnh cho các tác vụ này, bạn vẫn có thể thực hiện tất cả các bước trong một lần chạy. Hãy tự mình thử.

Bây giờ, hãy thay thế các mã trạm bằng các vị trí trạng thái của chúng bằng cách sử dụng AWK, có hiệu suất cao về mặt chức năng để xử lý dữ liệu lớn.

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

Đây là ý nghĩa của các thông số này:

-F, Dấu phân tách trường là ,
FNR Số dòng trong mỗi tệp
NR Số dòng trong cả hai tệp cùng nhau
FNR==NR Chỉ có trong tệp đầu tiên ${PATTERN_FILE}
{ x[$1]=$2; next; } Nếu FNR==NR là TRUE (cho tất cả các dòng trong $PATTERN_FILE duy nhất)
- x Biến để lưu trữ station=state bản đồ
- x[$1]=$2 Thêm dữ liệu của station=state bản đồ
- $1 Cột đầu tiên trong tệp đầu tiên (mã trạm)
- $2 Cột thứ hai trong tệp đầu tiên (mã tiểu bang)
- x Bản đồ của tất cả các trạm, ví dụ:x[US009052008]=SD , x[US10RMHS145]=CO , ..., x[USW00096409]=AK
- next Chuyển đến dòng tiếp theo đối sánh FNR==NR (về cơ bản, điều này tạo ra một bản đồ của tất cả các trạng thái trạm từ ${PATTERN_FILE}
{ $1=x[$1]; print $0 } Nếu FNR==NR là FALSE (cho tất cả các dòng in $DATA_FILE duy nhất)
- $1=x[$1] Thay thế trường đầu tiên bằng x[$1]; về cơ bản, thay thế mã trạm bằng mã tiểu bang
- print $0 In tất cả các cột (bao gồm cả $1 đã thay thế )
OFS=, Dấu phân tách các trường đầu ra là ,

CSV có mã trạm:

$ 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

Chạy lệnh:

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

Các trạm hiện được ánh xạ tới các trạng thái:

$ 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

Mỗi tiểu bang đều có một số chỉ số nhiệt độ cho mỗi ngày, vì vậy bạn cần tính giá trị trung bình của các chỉ số của mỗi tiểu bang trong một ngày. Sử dụng AWK để xử lý văn bản, sắp xếp để đảm bảo kết quả cuối cùng theo thứ tự hợp lý và rm để xóa tệp tạm thời sau khi xử lý.

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

Đây là ý nghĩa của các tham số AWK:

FILE=$DATA_FILE Tệp CSV được xử lý dưới dạng FILE
-F, Dấu phân tách trường là ,
state_day_sum[$1 "," $2 "," $3 "," $4] = $5

state_day_sum[$1 "," $2 "," $3 "," $4] + $5
Tổng nhiệt độ ($5 ) cho trạng thái ($1 ) vào năm ($2 ), tháng ($3 ), ngày ($4 )
state_day_num[$1 "," $2 "," $3 "," $4] = $5

state_day_num[$1 "," $2 "," $3 "," $4] + 1
Số lần đọc nhiệt độ cho trạng thái ($1 ) vào năm ($2 ), tháng ($3 ), ngày ($4 )
END Cuối cùng, sau khi thu thập tổng và số lần đọc cho tất cả các trạng thái, năm, tháng, ngày, hãy tính giá trị trung bình
for (state_day_key in state_day_sum) Đối với mỗi tiểu bang-năm-tháng-ngày
print state_day_key "," state_day_sum[state_day_key]/state_day_num[state_day_key] Trạng thái in, năm, tháng, ngày, trung bình
OFS=, Dấu phân tách các trường đầu ra là ,
$DATA_FILE Tệp đầu vào (tất cả các tệp có tên bắt đầu bằng TAVG_US_ và kết thúc bằng .csv , từng cái một)
> STATE_DAY_${DATA_FILE}.tmp Lưu kết quả vào tệp tạm thời

Chạy tập lệnh:

$ ./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

Các tệp này được tạo:

$ 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

Xem dữ liệu một năm cho tất cả các trạng thái (ít hơn là một tiện ích để xem đầu ra một trang tại một thời điểm):

$ 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

Hợp nhất tất cả các tệp dữ liệu thành một:

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

Giờ đây, bạn có một tệp, với tất cả các trạng thái, cho tất cả các năm:

$ 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. Tạo dữ liệu chuỗi thời gian

Một vấn đề như thế này được giải quyết một cách phù hợp với mô hình chuỗi thời gian như bộ nhớ ngắn hạn dài (LSTM), là mạng nơ-ron định kỳ (RNN). Dữ liệu đầu vào này được sắp xếp thành các lát thời gian; coi 20 ngày là một lát.

Đây là phần một lần (như trong 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

Phần thời gian này được biểu thị bằng (các giá trị nhiệt độ trong đó 20 tuần đầu tiên là X và 21 là y):

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

Các lát cắt liền kề nhau theo thời gian. Ví dụ:cuối năm 2010 tiếp tục sang năm 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

Kết quả dự đoán:

AK,2011,01,11,-106.851

Phần thời gian này được coi là:

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

và như vậy, cho tất cả các tiểu bang, năm, tháng và ngày. Để biết thêm giải thích, hãy xem hướng dẫn này về dự báo chuỗi thời gian.

Viết tập lệnh để tạo các lát thời gian:

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

Chạy tập lệnh. Nó sử dụng khoảng trắng làm dấu phân cách cột; đặt chúng thành dấu phẩy với sed:

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

Đây là vài dòng đầu tiên và vài dòng cuối cùng của đầu ra .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

Mặc dù điều này có hiệu quả, nhưng nó không hiệu quả lắm. Nó có thể được tối ưu hóa — bạn có thể thử không? Báo cáo trong phần nhận xét bên dưới cách bạn đã làm.

5. Tạo huấn luyện, kiểm tra và xác thực tập dữ liệu

Tách dữ liệu thành train , kiểm tra xác thực bộ.

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

Điều này tạo ra các tập dữ liệu có thể tuần tự hoặc ngẫu nhiên bằng cách đặt GEN=SEQ hoặc GEN=RAN trong script và bạn có thể trộn dữ liệu bằng shuf.

Chạy tập lệnh:

$ ./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

Để tạo các tệp dữ liệu này:

$ 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

Xử lý dữ liệu với shell

Khi bạn cần xử lý một lượng lớn dữ liệu cho dự án học máy tiếp theo của mình, hãy nghĩ đến các lệnh và tập lệnh shell. Nó đã được chứng minh và sẵn sàng sử dụng với các cộng đồng thân thiện để hướng dẫn và giúp đỡ bạn.

Bài viết này giới thiệu một trình bao để xử lý dữ liệu và các tập lệnh thể hiện các cơ hội. Nhiều hơn nữa là có thể. Bạn có muốn đưa nó về phía trước? Hãy cho chúng tôi biết trong phần bình luận bên dưới.