Recursos Machine Learning da Microsoft – Data Visualization

Olá pessoal! Sejam bem-vindos ao blog talkitbr. Neste artigo irei continuar a jornada para desvendar recursos Machine Learning da Microsoft.

Neste artigo irei explorar um pouco o que já foi apresentado nos artigos anteriores e também apresentarei novos recursos que você pode utilizar no momento de criar seu experimento de Machine Learning.

Etapa de Preparação dos Dados

Conforme já citado anteriormente, uma etapa importante e dispendiosa do Machine Learning é justamente entender os dados que dispomos e transformá-lo, através do data engineering, normalização, remoção de outliers, oversampling, data prune, etc.

Esse processo é contínuo. E muitas vezes as respostas obtidas em um modelo de Machine Learning podem nos levar novamente a etapa de preparação de dados com o objetivo de incluir/modificar dados para tentar obter resultados melhores.

Apesar de não ser o foco desses artigos da série, segue um esquema do modelo CRoss Industry Standard Process for Data Mining (CRISP-DM), que nos auxiliará a identificar as etapas envolvidas na preparação dos dados:

desvendandorecursosml_crispdmNote que a Preparação dos Dados é a etapa que precede a criação do modelo de Machine Learning.

A seguir irei apresentar alguns recursos para Exploração dos Dados, que é parte das etapas de Entendimento dos DadosPreparação dos Dados. Para isso irei utilizar um dataset the Bike Sharing disponibilizado pela UCI (University of California, Irvine Machine Learning Repository).

Usando MLStudio para Exploração dos Dados

Dos recursos apresentados, vamos focar agora no MLStudio (para saber mais sobre MLStudio, acesse os artigos anteriores desta série):

  1. Acesse o site https://studio.azureml.net
  2. Clique no botão para fazer login
  3. Será solicitada uma conta Microsoft. Se não tiver, crie uma gratuitamente.
  4. Você será redirecionado para a tela inicial do MLStudio.
  5. Em EXPERIMENTS, clique em New -> Blank Experiment
  6. Será exibido um Toolbox a esquerda e uma área de edição do experimento no centro da tela. Escolha a opção “Blank Experiment”.
  7. Vamos adicionar um nome para o experimento. Para isso, clique no texto “Experiment Created on …”. No meu caso irei especificar “Regression – Bike Rental”.
    • Se você já possui experimento criado com o dataset Bike Rental UCI, então pode pular esta etapa.
  8. O próximo passo é incluir o Dataset. Vamos usar um Dataset já disponível no MLStudio: o “Bike Rental UCI dataset”.
  9. Para colocá-lo no experimento, basta realizar o Drag&Drop do Dataset contido em “Saved Datasets -> Samples” para dentro da área de edição do experimento:fig5
  10. Para visualizar os dados originais, basta clicar na saída do módulo Bike Rental UCI dataset e selecionar a opção Visualize.desvendandorecursosml_visualizebikesharing

Adicionando coluna com nome do dia da semana

  1. Vamos iniciar a preparação de dados fazendo uma modificação nos valores de uma coluna. Vamos transformar a coluna weekday em valor texto para auxiliar na análise descritiva dos dados.
  2. Para isso, vamos adicionar um módulo de execução de script para executarmos código R ou Python dentro do nosso experimento:
    • Linguagem R: adicionar módulo Execute R Script e especificar o seguinte código:
    • set.day.of.week <- function() {
          library(dplyr)
          ##first day in the dataset is saturday
          data.frame(weekday = c(0, 1, 2, 3, 4, 5, 6),
          dayOfWeek = c ("Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"))
      }
      
      df <- set.day.of.week()
      maml.mapOutputPort('df')
    • Linguagem Python: adicionar módulo Execute Python Script e especificar o seguinte código:
    • def day_of_week():
          import pandas as pd
          ## First day in the dataset is Sunday
          days = pd.DataFrame([[0, 1, 2, 3, 4, 5, 6], ["Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"]]).transpose()
          days.columns = ['weekday', 'dayOfWeek']
          return days
      
      def azureml_main():
          return day_of_week()
  3. Esses Scripts disponibilizam um dataset simples para incluir informação do dia da semana no Dataset original.
    • Note que podemos incluir até 2 datasets e um Zip com scripts nos módulos Execute R Script e Execute Pyhton Script. Isso é muito útil pois permite reaproveitarmos bibliotecas de código que temos disponíveis.
  4. Aqui vou seguir com o procedimento para Pyhton, mas o mesmo pode ser feito em R.
  5. Vamos agora incluir módulo Join Data que permite fazer junção de dois datasets, que neste caso são o original e o dataset com o nome dos dias da semana.
    • Conecte a saída “1” do Bike Rental UCI dataset na entrada “1” do Join Data
    • Conecte a saída “1” do Execute Python Script na entrada “2” do Join Data
    • Selecione o módulo Join Data. Em Properties (lado direito do experimento), especifique os seguintes valores:
      • Join Keys columns for L: weekday
      • Join Keys columns for R: weekday (só irá aparecer para seleção quando executarmos o script pela primeira vez)
      • Match case: checked
      • Join type: Left outer join
      • Keep right key columns in joined table: unckecked
  6. Depois disso, execute o experimento:desvendandorecursosml_afterjoin
  7. Como resultado, teremos uma nova coluna no final do Dataset. Para visualizar, basta clicar na saída “1” do módulo Join Data e clicar em “Visualize”.desvendandorecursosml_weekday

Contabilizando o dia com base na coluna dteday

Uma das colunas do Dataset é o dteday que tem formado de 24 horas indicando os dias passados desde o primeiro dia da coleta. Vamos então criar uma nova coluna para indicar quantas dias passaram desde a primeira coleta:

  1. Adicione um novo módulo de execução de script para executarmos código R ou Python dentro do nosso experimento:
    • Linguagem R: adicionar módulo Execute R Script e especificar o seguinte código:
    • set.days <- function(df){
          df[,'days'] = as.integer(df[, 'instant']/24)
          df
      }
      
      df <- maml.mapInputPort(1)
      df <- set.days(df)
      maml.mapOutputPort('df')
    • Linguagem Python: adicionar módulo Execute Python Script e especificar o seguinte código:
    • def set_days(df):
          import pandas as pd
          df['days'] = pd.Series(range(df.shape[0]))/24
          df['days'] = df['days'].astype('int')
          return df
      
      def azureml_main(df):
          return set_days(df)
  2. No meu exemplo eu usei agora o módulo Execute R Script. Isso porque é possível intercalar scripts R e Python dentro do nosso experimento.
  3. Conecte a saída “1” do módulo Join Data na entrada “1” do módulo de execução de script.
  4. Execute o experimento.
  5. Visualize os dados resultantes:desvendandorecursosml_elapseddays

Seleção e Normalização dos Dados

Muitas vezes precisamos modificar os dados que dispomos de forma a excluir dados que não são relevantes e também normalizar dados para minimizar discrepância de valores. Em ambos os casos temos perda de dados, sendo que no segundo, a perda é relativa já que a normalização é feita com base no valor original.

Portanto, deve-se ter cautela nesse momento para evitar modificar os dados que estamos trabalhando. Como resultado podemos obter valores que podem mais prejudicar do que ajudar no entendimento dos dados e posterior criação do modelo de Machine Learning.

Mas essa é uma vantagem do MLStudio, pois podemos criar vários fluxos de módulos dentro do experimento para testar opções de seleção e normalização de dados. Vamos então voltar ao MLStudio:

  1. Adicione o módulo Select Columns in Dataset logo após o segundo módulo de Execução de Script:
    • Conecte a saída “1” do Execute Script na entrada “1” do Select Columns in Dataset
    • Selecione o módulo Select Columns in Dataset. Em Properties (lado direito do experimento), especifique os seguintes valores:
      • Select columns:
        • Escolha a opção WITH RULES na lateral esquerda
        • Marque o item “ALL COLUMNS”
        • Exclua as seguintes colunas: instant, dteday, weekday, atemp, casual, registereddesvendandorecursosml_selectcolumns
  2. Depois disso, vamos normalizar os dados. A normalização é importante para evitar discrepâncias entre valores de uma determinada coluna. Essa discrepância pode impactar no modelo de Machine Learning que iremos criar. Exemplo:
    • Ao normalizar dado de temperatura, evitamos que picos de temperatura, que sejam muito discrepantes, tenham um peso muito grande no nosso modelo. Apesar de considerar a temperatura um dado relevante, queremos reduzir a discrepância de valores através da normalização.
  3. Adicione o módulo Normalize Data logo após o módulo Select Columns in Dataset
    • Conecte a saída “1” do Select Columns in Dataset na entrada “1” do Normalize Data
    • Selecione o módulo Normalize Data. Em Properties (lado direito do experimento), especifique os seguintes valores:
      • Transformation method: ZScore (existem várias opções de normalização disponíveis no MLStudio).
      • Use 0 for constants when checked: checked.
      • Select columns:
        • Escolha a opção WITH RULES na lateral esquerda
        • Marque o item “NO COLUMN”
        • Inclua as seguintes colunas pelo nome: temp, hum, windspeed
  4. Execute o experimento. Ao termino desta etapa teremos o se resultado:desvendandorecursosml_normalizedata

Visualização de Dados em Gráficos

Conforme visto no artigo anterior, a qualquer momento podemos converter os dados do experimento em CSV e manipulá-los através de um Jupyter Notebook usando linguagens R e Python. Mas aqui vou explorar a opção de definir o Script no próprio experimento.

Porém para o que queremos fazer aqui, a plotagem de gráficos no Python é mais apropriada no Jupyter Notebook. Então vamos seguir duas estratégias de acordo com sua linguagem de preferência:

  1. Para Linguagem R, adicione o módulo Execute R Script:
    • Conecte a saída “1” do módulo Normalize Data na entrada “1” do módulo Execute R Script
    • Especifique o seguinte código no módulo Execute R Script:
    • numCols <- c("temp", "hum", "windspeed", "hr")
      bike.scatter <- function(df, cols){
           require(ggplot2)
           for(col in cols){
               p1 <- ggplot(df, aes_string(x = col, y = "cnt")) +
               geom_point(aes(alpha = 0.001, color = "blue")) +
               geom_smooth(method = "loess") +
               ggtitle(paste('Count of bikes rented vs. ', col)) +
               theme(text = element_text(size=16))
               print(p1)
           }
      }
      
      catCols <- c('season', 'yr', 'mnth', 'hr', 'holiday', 'workingday', 'weathersit', 'dayOfWeek')
          bike.box <- function(df, cols) {
          require(ggplot2)
          for(col in cols) {
              p1 <- ggplot(df, aes_string(x = col, y = 'cnt', group = col)) +
               geom_boxplot()+
               ggtitle(paste('Count of bikes rented vs. ', col)) +
               theme(text = element_text(size=16))
               print(p1)
          }
      }
      
      pltTimes = c(6, 8, 10, 12, 14, 16, 18, 20)
      bike.series <- function(df, tms){
          require(ggplot2)
          ylims = c(min(df$cnt), max(df$cnt))
          for(t in tms){
               temp = df[df$hr == t, ]
               p1 <- ggplot(temp, aes(x = days, y = cnt)) +
               geom_line() +
               ylim(ylims) +
               ylab('Bikes rented') +
               ggtitle(paste('Count of bikes rented vs. time for', t, 'hour of the day')) +
               theme(text = element_text(size=16))
               print(p1)
          }
      }
      
      histCols <- c("temp", "hum", "windspeed", "cnt")
          bike.hist <- function(df, cols){
              require(ggplot2)
              for(col in cols){
              p1 <- ggplot(df, aes_string(x = col)) +
                  geom_histogram() +
                  ggtitle(paste('Density of', col)) +
                  theme(text = element_text(size=16))
              print(p1)
          }
      }
      
      bike.hist.cond <- function(df, tms) {
          require(ggplot2)
          
          # require(gridExtra)
          par(mfrow = c(2,4))
          for(i in 1:length(tms)){
              temp = df[df$hr == tms[i], ]
              p <- ggplot(temp, aes(x = cnt)) +
              geom_histogram() +
              ggtitle(paste('Density of bike rentals at time', as.character(tms[i]))) +
                              theme(text = element_text(size=16))
              print(p)
          }
          # grid.arrange(grobs = p, ncol = 3)
          par(mfrow = c(1,1))
      }
      
      # Map 1-based optional input ports to variables
      dat <- maml.mapInputPort(1) # class: data.frame
      bike.scatter(dat, numCols)
      bike.box(dat, catCols)
      bike.series(dat, pltTimes)
      
    • Execute o experimento.
    • Após o término da execução, clique na saída “2” do módulo Execute R Script e visualize os dados (que nesse caso são o resultado da execução do Script e não o dataset retornado).desvendandorecursosml_graphicsinr
  2. Para Linguagem Python, adicione o módulo Convert to CSV 
    • Conecte a saída “1” do módulo Normalize Data na entrada “1” do módulo Convert to CSV
    • Execute o experimento.
    • Clique na saída “1” do módulo Convert to CSV e escolha a opção “Open in a new Notebook -> Python 2”desvendandorecursosml_convertcsv
    • Especifique as seguintes células no Notebook, logo após a primeira célula que carrega o Dataset:
num_cols = ["temp", "hum", "windspeed", "hr"]

def bike_scatter(df, cols):
     import matplotlib.pyplot as plt
     import statsmodels.nonparametric.smoothers_lowess as lw

     ## Loop over the columns and create the scatter plots
     for col in cols:
         ## first compute a lowess fit to the data
         los = lw.lowess(df['cnt'], df[col], frac = 0.3)

         ## Now make the plots
         fig = plt.figure(figsize=(8, 6))
         fig.clf()
         ax = fig.gca()
         df.plot(kind = 'scatter', x = col, y = 'cnt', ax = ax, alpha = 0.05)
         plt.plot(los[:, 0], los[:, 1], axes = ax, color = 'red')
         ax.set_xlabel(col)
         ax.set_ylabel('Number of bikes')
         ax.set_title('Number of bikes vs. ' + col)
     return 'Done'

cat_cols = ['season', 'yr', 'mnth', 'hr', 'holiday', 'workingday', 'weathersit', 'dayOfWeek']

def bike_box(df, cols):
    import matplotlib.pyplot as plt

    ## Loop over the columns and create the box plots
    for col in cols:
        fig = plt.figure(figsize=(8, 6))
        fig.clf()
        ax = fig.gca()
        df.boxplot(column = 'cnt', by = col, ax = ax)
        ax.set_xlabel(col)
        ax.set_ylabel('Number of bikes')
        ax.set_title('Number of bikes vs. ' + col)
    return 'Done'

plt_times = [6, 8, 10, 12, 14, 16, 18, 20]
def bike_series(df, tms):
    import matplotlib.pyplot as plt

    lims = (min(df.cnt), max(df.cnt))
    for t in tms:
        fig = plt.figure(figsize=(8, 6))
        fig.clf()
        ax = fig.gca()
        df[df.hr == t].plot(kind = 'line', x = 'days', y = 'cnt',
        ylim = lims, ax = ax)
        plt.xlabel("Days from start")
        plt.ylabel("Bikes rented")
        plt.title("Bikes rented by day for hour = " + str(t))
    return 'Done'

hist_cols = ["cnt", "temp", "hum", "windspeed"]
def bike_hist(df, cols):
    import matplotlib.pyplot as plt

    ## Loop over columns and plot histograms
    for col in cols:
        fig = plt.figure(figsize=(8, 6))
        fig.clf()
        ax = fig.gca()
        df[col].hist(bins = 30, ax = ax)
        ax.set_xlabel(col)
        ax.set_ylabel('Density of ' + col)
        ax.set_title('Density of ' + col) 

    return 'Done'

def bike_hist_cond(df, col, by):
    import matplotlib.pyplot as plt

    df = df[df.hr.isin(by)]
    ## Plot conditioned histograms
    fig = plt.figure(figsize=(10, 8))
    ax = fig.gca()
    df[[col, 'hr']].hist(bins = 30, by = ['hr'], ax = ax)
    return 'Done'
%matplotlib inline
bike_scatter(frame, num_cols)
bike_box(frame, cat_cols)
bike_series(frame, plt_times)
bike_hist(frame, hist_cols)
bike_hist_cond(frame, 'cnt', plt_times)

desvendandorecursosml_notebookpython

Execute as células. O Jupyter Notebook irá exibir os gráficos logo após a execução dos mesmos.desvendandorecursosml_notebookpythonplot

Ao término desse procedimento (tanto usando linguagem R como Python), teremos vários gráficos que nos permitem analisar os dados. Podemos por exemplo avaliar quantas bicicletas são compartilhadas de acordo com a temperatura e humidade; quais horários temos maior incidência de compartilhamento de bicicletas; número de bicicletas por mês; etc.

E para isso temos diferentes tipos de gráficos. Não é propósito deste artigo explicar conceitos destes gráficos, mas segue breve descrição do que obtivemos:

  • Scatter Plot: permite plotar a relação entre dois ou mais dados do dataset
  • Box Plot: fornece informações de variação de números, mediana e valores que podem indicar presença de outliers;
  • Histogramas: que contabilizam valores de acordo com critério de distribuição de intervalos (bins)

Considerações Finais

Este artigo teve como propósito apresentar brevemente recursos do MLStudio para visualização de dados que nos auxiliam na etapa de entendimento dos dados dentro do processo de descoberta de conhecimento CRISP-DM.

Nos próximos artigos irei descrever outros exemplos de experimentos utilizando mais recursos do MLStudio, R e Python. Além disso, iremos explorar outros recursos como Máquina Virtual da DataScience, Microsoft Azure Workbench, HDInsight e Microsoft Azure Databricks.

Até o próximo artigo!

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s