Crie um modelo de aprendizado de máquina com Bash
Bash, Tcsh ou Zsh podem ajudá-lo a se preparar para o aprendizado de máquina.
O aprendizado de máquina é uma capacidade computacional poderosa para prever ou prever coisas que os algoritmos convencionais consideram desafiadoras. A jornada de aprendizado de máquina começa com a coleta e preparação de dados (muitos) e, em seguida, constrói modelos matemáticos com base nesses dados. Embora várias ferramentas possam ser usadas para essas tarefas, gosto de usar o shell.
Um shell é uma interface para realizar operações usando uma linguagem definida. Esta linguagem pode ser invocada de forma interativa ou por script. O conceito de shell foi introduzido nos sistemas operacionais Unix na década de 1970. Alguns dos shells mais populares incluem Bash, tcsh e Zsh. Eles estão disponíveis para todos os sistemas operacionais, incluindo Linux, macOS e Windows, o que lhes confere alta portabilidade. Para este exercício, usarei o Bash.
Este artigo é uma introdução ao uso de um shell para coleta e preparação de dados. Quer você seja um cientista de dados em busca de ferramentas eficientes ou um especialista em shell que deseja usar suas habilidades para aprendizado de máquina, espero que encontre informações valiosas aqui.
O exemplo de problema neste artigo é a criação de um modelo de aprendizado de máquina para prever temperaturas para os estados dos EUA. Ele usa comandos e scripts shell para executar as seguintes etapas de coleta e preparação de dados:
- Baixar dados
- Extraia os campos necessários
- Dados agregados
- Faça séries temporais
- Criar conjuntos de dados para treinar, testar e validar
Você pode estar se perguntando por que deveria fazer isso com shell, quando você pode fazer tudo isso em uma linguagem de programação de aprendizado de máquina como Python. Essa é uma boa pergunta. Se o processamento de dados for realizado com uma tecnologia fácil, amigável e rica como um shell, um cientista de dados se concentrará apenas na modelagem do aprendizado de máquina e não nos detalhes de uma linguagem.
Pré-requisitos
Primeiro, você precisa ter um interpretador de shell instalado. Se você usa Linux ou macOS, ele já estará instalado e você já deve estar familiarizado com ele. Se você usa Windows, experimente MinGW ou Cygwin.
Para mais informações, veja:
- Tutoriais de Bash aqui em opensource.com
- O tutorial oficial de script de shell de Steve Parker, o criador do Bourne Shell
- O Guia Bash para Iniciantes do Projeto de Documentação Linux
- Se precisar de ajuda com um comando específico, digite
no shell para obter ajuda; por exemplo:--help ls --help
.
iniciar
Agora que seu shell está configurado, você pode começar a preparar dados para o problema de previsão de temperatura de aprendizado de máquina.
1. Baixe dados
Os dados para este tutorial vêm da Administração Nacional Oceânica e Atmosférica dos EUA (NOAA). Você treinará seu modelo usando os dados dos últimos 10 anos completos. A fonte de dados está em https://www1.ncdc.noaa.gov/pub/data/ghcn/daily/by_year/, e os dados estão no formato .csv e compactados em gzip.
Baixe e descompacte os dados usando um script de shell. Use seu editor de texto favorito para criar um arquivo chamado download.sh
e cole o código abaixo. Os comentários no código explicam o que os comandos fazem:
#!/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
Notas :
Se você estiver atrás de um servidor proxy, consulte as instruções de Mark Grennan e use:
export http_proxy=http://username:password@proxyhost:port/ export https_proxy=https://username:password@proxyhost:port/
- Certifique-se de que todos os comandos padrão já estejam em seu PATH (como
/bin
ou/usr/bin
). Caso contrário, defina seu PATH. - Wget é um utilitário para conectar-se a servidores web a partir da linha de comando. Se o Wget não estiver instalado em seu sistema, baixe-o.
- Certifique-se de ter o gzip, um utilitário usado para compactação e descompactação.
Execute este script para baixar, extrair e disponibilizar dados de 10 anos como 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
...
O comando ls lista o conteúdo de uma pasta. Use ls 20*.csv
para listar todos os seus arquivos com nomes começando com 20 e terminando com .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. Extraia temperaturas médias
Extraia os dados TAVG (temperatura média) dos CSVs para regiões dos EUA:
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
Este roteiro:
$ ./extract_tavg_us.sh
2010.csv -> TAVG_US_2010.csv
...
2019.csv -> TAVG_US_2019.csv
cria estes arquivos:
$ 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
Aqui estão as primeiras linhas de 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,
O comando head é um utilitário para exibir as primeiras linhas (por padrão, 10 linhas) de um arquivo.
Os dados contêm mais informações do que você precisa. Limite o número de colunas eliminando a coluna 3 (já que todos os dados são de temperatura média) e a coluna 5 em diante. Em outras palavras, mantenha as colunas 1 (estação climática), 2 (data) e 4 (temperatura registrada).
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
Execute o script:
$ ./key_columns.sh
Extracting columns TAVG_US_2010.csv
...
Extracting columns TAVG_US_2019.csv
As primeiras linhas de TAVG_US_2010.csv
com os dados desnecessários removidos são:
$ 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
As datas estão em formato de string (YMD). Para treinar seu modelo corretamente, seus algoritmos precisam reconhecer campos de data no formato Y,M,D separados por vírgula (por exemplo, 20100101
se torna 2010,01,01
) . Você pode convertê-los com o utilitário sed.
formato_de_data.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
Execute o script:
$ ./date_format.sh
Date formatting TAVG_US_2010.csv
...
Date formatting TAVG_US_2019.csv
As primeiras linhas de TAVG_US_2010.csv
com o formato de data separado por vírgula são:
$ 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. Dados agregados de temperatura média dos estados
Os dados meteorológicos vêm de estações climáticas localizadas em cidades dos EUA, mas você deseja prever as temperaturas de estados inteiros. Para converter os dados das estações climáticas em dados estaduais, primeiro mapeie as estações climáticas para seus estados.
Baixe a lista de estações climáticas usando wget:
$ wget ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/daily/ghcnd-stations.txt
Extraia as estações dos EUA com o utilitário grep para encontrar listagens dos EUA. O comando a seguir procura linhas que começam com o texto "US
." O >
é um redirecionamento que grava a saída em um arquivo — neste caso, em um arquivo chamado us_stations.txt
:
$ grep "^US" ghcnd-stations.txt > us_stations.txt
Este arquivo foi criado para impressão bonita, portanto os separadores de colunas são inconsistentes:
$ 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
...
Torne-os consistentes usando cat para imprimir o arquivo, usando tr para comprimir repetições e gerar saída para um arquivo temporário e renomeando o arquivo temporário de volta ao original - tudo em uma linha:
$ cat us_stations.txt | tr -s ' ' > us_stations.txt.tmp; cp us_stations.txt.tmp us_stations.txt;
As primeiras linhas da saída do comando:
$ 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
...
Contém muitas informações – coordenadas GPS e outras coisas – mas você só precisa do código da estação e do estado. Usar corte:
$ cut -d' ' -f1,5 us_stations.txt > us_stations.txt.tmp; mv us_stations.txt.tmp us_stations.txt;
As primeiras linhas da saída do comando:
$ head us_stations.txt
US009052008 SD
US10RMHS145 CO
US10adam001 NE
US10adam002 NE
...
Transforme isso em CSV e altere os espaços para separadores de vírgula usando sed:
$ sed -i s/' '/,/g us_stations.txt
As primeiras linhas da saída do comando:
$ head us_stations.txt
US009052008,SD
US10RMHS145,CO
US10adam001,NE
US10adam002,NE
...
Embora você tenha usado vários comandos para essas tarefas, é possível executar todas as etapas de uma só vez. Tente você mesmo.
Agora, substitua os códigos de estação por seus locais de estado usando AWK, que tem funcionalidade de alto desempenho para processamento de grandes dados.
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
Aqui está o que esses parâmetros significam:
-F,
O separador de campos é
,
FNR
Número da linha em cada arquivo
NR
Número da linha em ambos os arquivos juntos
FNR==NR
É TRUE apenas no primeiro arquivo
$ {PATTERN_FILE}
{ x[$1]=$2; next; }
Se
FNR==NR
for TRUE (somente para todas as linhas em$PATTERN_FILE
)- x
Variável para armazenar o mapa
station=state
- x[$1]=$2
Adiciona dados de
station=state
ao mapa- $1
Primeira coluna no primeiro arquivo (códigos de estação)
- $2
Segunda coluna no primeiro arquivo (códigos de estado)
- x
Mapa de todas as estações, por exemplo,
x[US009052008]=SD
,x[US10RMHS145]=CO
, ...,x[USW00096409]=AK
- next
Vá para a próxima linha correspondente a
FNR==NR
(essencialmente, isso cria um mapa de todos os estados-estações do$ {PATTERN_FILE}
{ $1=x[$1]; print $0 }
Se
FNR==NR
for FALSE (somente para todas as linhasem $DATA_FILE
)- $1=x[$1]
Substitua o primeiro campo por
x[$1]
; essencialmente, substitua o código da estação pelo código do estado- print $0
Imprima todas as colunas (incluindo
$1
substituído)OFS=,
O separador dos campos de saída é
,
O CSV com códigos de estação:
$ 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
Execute o comando:
$ ./station_to_state_data.sh
TAVG_US_2010.csv
...
TAVG_US_2019.csv
As estações agora estão mapeadas para estados:
$ 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
Cada estado tem várias leituras de temperatura para cada dia, então você precisa calcular a média das leituras de cada estado para um dia. Use AWK para processamento de texto, classifique para garantir que os resultados finais estejam em uma ordem lógica e rm para excluir o arquivo temporário após o processamento.
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
Aqui está o que os parâmetros AWK significam:
FILE=$DATA_FILE
Arquivo CSV processado como
FILE
-F,
O separador de campos é
,
state_day_sum[$1 "," $2 "," $3 "," $4] = $5
state_day_sum[$1 "," $2 "," $3 "," $4] + $5Soma da temperatura (
$5
) para o estado($1
) no ano ($2
), mês ($3
) , dia ($4
)state_day_num[$1 "," $2 "," $3 "," $4] = $5
state_day_num[$1 "," $2 "," $3 "," $4] + 1Número de leituras de temperatura para o estado (
$1
) no ano ($2
), mês ($3
), dia ($4
código>)END
Ao final, após coletar a soma e o número de leituras de todos os estados, anos, meses, dias, calcule as médias
for (state_day_key in state_day_sum)
Para cada estado-ano-mês-dia
print state_day_key "," state_day_sum[state_day_key]/state_day_num[state_day_key]
Imprimir estado, ano, mês, dia, média
OFS=,
O separador dos campos de saída é
,
$DATA_FILE
Arquivo de entrada (todos os arquivos com nome começando com
TAVG_US_
e terminando com.csv
, um por um)> STATE_DAY_${DATA_FILE}.tmp
Salvar o resultado em um arquivo temporário
Execute o script:
$ ./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
Esses arquivos são criados:
$ 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
Veja um ano de dados para todos os estados (menos é um utilitário para ver a saída de uma página por vez):
$ 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
Mesclar todos os arquivos de dados em um:
$ cat STATE_DAY_TAVG_US_20*.csv > TAVG_US_2010-2019.csv
Agora você tem um arquivo, com todos os estados, para todos os anos:
$ 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. Crie dados de série temporal
Um problema como esse é adequadamente abordado com um modelo de série temporal, como a memória de longo e curto prazo (LSTM), que é uma rede neural recorrente (RNN). Esses dados de entrada são organizados em intervalos de tempo; considere 20 dias como uma fatia.
Esta é uma fatia única (como em 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
Esse intervalo de tempo é representado como (valores de temperatura em que as primeiras 20 semanas são X e 21 são y):
AK, -181.934,-199.531, ... ,
-157.273,-165.3
As fatias são contíguas no tempo. Por exemplo, o final de 2010 continua em 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
O que resulta na previsão:
AK,2011,01,11,-106.851
Este intervalo de tempo é considerado como:
AK, -209.92, ... ,-79.8523,-59.5658, ... ,-100.623,-106.851
e assim por diante, para todos os estados, anos, meses e datas. Para obter mais explicações, consulte este tutorial sobre previsão de série temporal.
Escreva um script para criar intervalos de tempo:
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
Execute o script. Ele usa espaços como separadores de colunas; coloque vírgulas com sed:
$ ./timeslices.sh > TIMESLICE_TAVG_US_2010-2019.csv; sed -i s/' '/,/g TIME_VARIANT_TAVG_US_2010-2019.csv
Aqui estão as primeiras e as últimas linhas do .csv de saída:
$ 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
Embora isso funcione, não tem muito desempenho. Ele pode ser otimizado – você pode tentar? Relate nos comentários abaixo como você fez isso.
5. Crie, treine, teste e valide conjuntos de dados
Divida os dados em conjuntos train, test e validate.
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
Isso gera conjuntos de dados que podem ser sequenciais ou aleatórios definindo GEN=SEQ
ou GEN=RAN
no script, e você pode embaralhar os dados com shuf.
Execute o script:
$ ./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
Para criar esses arquivos de dados:
$ 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
Processamento de dados com shell
Quando você precisar processar uma enorme quantidade de dados para seu próximo projeto de aprendizado de máquina, pense em comandos e scripts shell. Está comprovado e pronto para uso com comunidades amigáveis para orientar e ajudar você.
Este artigo apresenta um shell para processamento de dados e os scripts demonstram oportunidades. Muito mais é possível. Você quer levar isso adiante? Conte-nos nos comentários abaixo.