Fala galera do mundo dos dados! Neste artigo nós iremos realizar uma Análise Exploratória de Dados (EDA) com ML.Net no ambiente WSL *Ubuntu (Linux). Dessa forma, dando prosseguimento com a construção de nosso exemplo de regressão linear para previsão de preços das residências em conjunto com um Dataset do Kaggle.
*É importante frisar que apesar o processo de instalação do ML.Net para usuários nativos do Ubuntu é semelhante ao utilizado no artigo para instalação no ambiente WSL.
Antes de tudo, vimos no artigo anterior criar aplicativos de Machine Learning utilizando C# nunca foi tão fácil!
Introdução ao ML.Net com Jupyter Notebooks.
Após o anúncio oficial do suporte ao ML.NET para Jupyter notebooks agora tivemos o anúncio do suporte ao novo tipo DataFrame que vem para facilitar a realização de exploração de dados.
Se você já utilizou a biblioteca Pandas em Python na manipulação dados em Jupyter notebooks, você já está familiarizado com o conceito de DataFrame. Em alto nível o DataFrame é uma representação em memória dos dados estruturados.
O Subsistema do Windows para Linux permite que os desenvolvedores executem um ambiente GNU/Linux, incluindo a maioria das ferramentas de linha de comando, utilitários e aplicativos, diretamente no Windows, sem modificações e sem a sobrecarga de uma máquina virtual tradicional ou da instalação em dualboot.
Todo o processo de instalação é detalhado neste artigo da Microsoft.
O Anaconda é uma distribuição gratuita e de código aberto, que visa simplificar o gerenciamento e a implantação de pacotes. A distribuição inclui pacotes de ciência de dados adequados para Windows, Linux e macOS.
Inicie o seu ambiente WSL e baixe o Anaconda:
wget https://repo.anaconda.com/archive/Anaconda3-2020.07-Linux-x86_64.sh
Em seguida vamos executar o arquivo para instalar o Anaconda:
bash Anaconda3-2020.07-Linux-x86_64.sh
Depois de seguir as instruções na tela para instalar o Anaconda você deve remover o arquivo de instalação:
rm Anaconda3-2020.07-Linux-x86_64.sh
Agora vamos iniciar o ambiente Anaconda:
source ~anaconda3/bin/activate
“~anaconda3/bin/activate” é o local padrão em que o Anaconda irá se instalar, mas se você escolher outro local, simplesmente aponte para esse diretório.
Uma vez que o ambiente esteja ativado nós iremos agora iniciar sua atualização completa:
conda update –all
Você configurou com sucesso o Anaconda 3 para um subsistema Windows para Linux!
O SDK do .NET Core é um conjunto de bibliotecas e ferramentas que permitem aos desenvolvedores criar bibliotecas e aplicativos do .NET Core. Sendo assim, Ele contém os seguintes componentes que são usados para criar e executar aplicativos.
Para configurar o SDK em ambiente WSL será necessário instalar:
wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb sudo apt-get update sudo apt-get install apt-transport-https sudo apt-get update sudo apt-get install dotnet-sdk-3.1
O .NET interactive é um conjunto de ferramentas CLI e APIs que permitem aos usuários criar experiências interativas em notebooks na web.
Para configurar o .NET interactive no ambiente WSL será necessário instalar:
dotnet tool install --global Microsoft.dotnet-interactive dotnet interactive jupyter install
Você poderá verificar a correta instalação da ferramenta executando o seguinte no prompt do Anaconda:
> jupyter kernelspec list .net-csharp ~\jupyter\kernels\.net-csharp .net-fsharp ~\jupyter\kernels\.net-fsharp .net-powershell ~\jupyter\kernels\.net-powershell python3 ~\jupyter\kernels\python3
Então agora que o nosso ambiente está configurado vamos iniciar o nosso estudo
Agora vamos iremos modificar o nosso modelo de regresso linear utilizado para prever os preços das residências usando os seus dados de tamanho e preço.
Antes de escrever qualquer código ML.NET, você precisa que o seu notebook tenha acesso aos pacotes NuGet que você irá utilizar. Nesse caso iremos usar o Microsoft.ML para criar o modelo de Regressão.
//Instalar os Pacotes do Nuget //ML.NET #r "nuget:Microsoft.ML" //ML.NET FastTree #r "nuget:Microsoft.ML.FastTree" //DataFrame #r "nuget:Microsoft.Data.Analysis" //XPlot #r "nuget:XPlot.Plotly,2.0.0"
Agora estamos prontos para adicionar o nosso código, então vamos adicionar as instruções de uso:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Microsoft.ML; using Microsoft.ML.Data; using Microsoft.Data.Analysis; using Microsoft.AspNetCore.Html; using Microsoft.ML.Trainers.FastTree; using System.IO; using System.IO.Compression; using System.Net.Http; using System.Globalization; using XPlot.Plotly; using static Microsoft.ML.TrainCatalogBase; using static Microsoft.ML.DataOperationsCatalog;
Neste artigo iremos utilizar o Dataset do California Housing Prices do Kaggle. Os seus dados contêm informações do censo de 1990 em Califórnia – USA. Sendo assim, ele vai nos ajudar a prever os preços de habitação servindo como um conjunto de dados introdutório para o nosso exemplo de machine learning.
Aqui está o código para download do Dataset:
if (!File.Exists(housingPath)) { var contents = new HttpClient() .GetStringAsync("https://raw.githubusercontent.com/ageron/handson-ml2/master/datasets/housing/housing.csv").Result; File.WriteAllText(housingPath, contents); }
Na versão atual a saída padrão do DataFrame não é a mais adequada para ser exibida como uma tabela. Contudo podemos implementar um formatador personalizado. Nós faremos isso conforme demonstrado no código abaixo:
Formatter.Register<DataFrame>((df, writer) => { var headers = new List<IHtmlContent>(); headers.Add(th(i("index"))); headers.AddRange(df.Columns.Select(c => (IHtmlContent) th(c.Name))); var rows = new List<List<IHtmlContent>>(); var take = 10; for (var i = 0; i < Math.Min(take, df.Rows.Count); i++) { var cells = new List<IHtmlContent>(); cells.Add(td(i)); foreach (var obj in df.Rows[i]) { cells.Add(td(obj)); } rows.Add(cells); } var t = table( thead( headers), tbody( rows.Select( r => tr(r)))); writer.Write(t); }, "text/html");
A Análise Exploratória de Dados ou EDA (Exploratory Data Analysis) é uma abordagem utilizada para analisar conjuntos de dados com o intuito resumir suas características principais e extrair informações úteis dos seus dados através de técnicas de visualizações
Munido dessas técnicas o cientista de dados é capaz por exemplo, de entender a natureza dos dados e formular algumas hipóteses sobre as informações que estão a sua disposição.
O DataFrame é um novo tipo introduzido em .Net. Ele é semelhante ao objeto DataFrame do Python, que é usado para manipular dados em notebooks. É uma coleção de colunas contendo dados semelhantes a uma tabela e muito útil na análise de dados tabulares. Tendo suporte para os métodos GroupBy, Sort, Filter, Join/Merge e para o tratamento de valores nulos o que o torna muito útil para a realização de análises.
Então, neste Artigo iremos cobrir seguintes os recursos do objeto DataFrame:
Aqui vamos utilizar o método “LoadCsv” para carregar os dados.
var df = DataFrame.LoadCsv(housingPath);
Podemos utilizar os métodos: df.Head(5),df.Sample(5) e df.Tail(5) para exibir os registros. Respectivamente estes comandos irão exibir registros do início, aleatórios e do final do arquivo.
Aqui temos as 10 colunas do Dataset dentre elas: Longitude, Latitude, Total_rooms, Total_bedrooms, Median_house_value
Também podemos usar os métodos df.AddPrefix(“HOUSE_”) e df.AddSuffix(“_data“) para adicionar um prefixo ou um sufixo aos nomes da colunas
O comando df.Description() exibe as estatísticas do total, máximo, mínimo e média para cada um dos itens em uma coluna do conjunto de dados.
O comando df.Info() exibe informações de tipo para cada coluna do conjunto de dados.
O processo de limpeza e preparação dos dados pode representar até 80% do trabalho de um cientista de dados (Dasu e Johnson 2003). Dessa forma, é uma atividade muito importante para a remoção os dados irrelevantes presentes em nosso conjunto de dados. Nesse sentido, os dados podem ser irrelevantes devido a valores ausentes, valores inválidos ou mesmo em razão de outliers.
Para manter este bloco de notas simples usaremos uma das técnicas mais simples que é remoção de valores Nulls. Mas, existem outras técnicas que também poderiam ser aplicadas aos dados com FillNull para preencher valores nulos com outros valores, como a média, moda ou a mediana.
df = df.DropNulls()
Para filtrar os dados pelos valores das colunas nós podemos utilizar os comandos ElementwiseEquals, ElementwiseGreaterThan, ElementwiseGreaterThanOrEqual, ElementwiseNotEquals, ElementwiseLessThan e ElementwiseLerssThanOrEqual.
Para facilitar o estudo do Dataset foram criadas algumas visualizações de acordo com as imagens abaixo:
Para carregar o conjunto de dados vamos precisar utilizar duas classes uma classe para a entrada de entrada e outra classe para a previsão, serão as classes ModelInput e ModelOutput.
public class ModelInput { [LoadColumn(0)] public float Longitude {get; set;} [LoadColumn(1)] public float Latitude {get; set;} [LoadColumn(2)] public float Housing_median_age {get; set;} [LoadColumn(3)] public float Total_rooms {get; set;} [LoadColumn(4)] public float Total_bedrooms {get; set;} [LoadColumn(5)] public float Population {get; set;} [LoadColumn(6)] public float Households {get; set;} [public (7)] public float Median_income {get; set;} [ColumnName("Label"), LoadColumn(8)] public float Median_house_value {get; set;} [LoadColumn(9)] public string Ocean_proximity {get; set;} } public class ModelOutput { [ColumnName("Score")] public float Score {get; set;} }
A primeira coisa que precisamos fazer é criar um objeto do tipo MLContext, esse é o objeto mais importante do ML.NET, praticamente tudo está ligado a ele. Sendo assim, um aplicativo ML.NET sempre irá iniciar com um objeto MLContext.
MLContext mlContext = new MLContext(seed: 1);
Como nós já vimos possuímos apenas um único dataset. E por isso vamos chamar o método TrainTestSplit() para configurar um set com 80% dos dados para treinamento e os 20% restantes para os testes.
private static IDataView trainingDataView; private static IDataView testingDataView; IDataView fullData = mlContext.Data.LoadFromTextFile<ModelInput>(path: housingPath, hasHeader: true, separatorChar: ',', allowQuoting: true, allowSparse: false); DataOperationsCatalog.TrainTestData trainTestData = mlContext.Data.TrainTestSplit(fullData, testFraction: 0.2); trainingDataView = trainTestData.TrainSet; testingDataView = trainTestData.TestSet;
Em ciência de dados é comum utilizar a divisão 80/20 para dividir os dados em treino e teste para um modelo.
Agora já estamos prontos para começar a construir o modelo de aprendizado de máquina:
Os modelos de aprendizado de máquina em ML.NET são criados como pipelines, que são sequências de componentes de carregamento, transformação e aprendizado de dados.
O nosso pipeline possui os seguintes componentes:
var dataProcessPipeline = mlContext.Transforms.Categorical.OneHotEncoding(new[] { new InputOutputColumnPair("Ocean_proximity", "Ocean_proximity") }) .Append(mlContext.Transforms.Concatenate("Features", new[] { "Ocean_proximity","Longitude", "Latitude", "Housing_median_age", "Total_rooms", "Total_bedrooms", "Population", "Households", "Median_income" }) .AppendCacheCheckpoint(mlContext)); var trainer = mlContext.Regression.Trainers.Sdca(labelColumnName: "Label", featureColumnName: "Features"); var trainingPipeline = dataProcessPipeline.Append(trainer);
O método Fit() treina o modelo com o conjunto de dados de treinamento fornecido. Isso é conhecido como treinamento do modelo. Lembre-se de que o modelo de regressão linear acima tem dois parâmetros de modelo: desvio e peso. Após a chamada a Fit(), os valores dos parâmetros são conhecidos.
var model = trainingPipeline.Fit(trainingDataView);
Agora vamos poder utilizar o modelo treinado para fazer as nossas previsões sobre os novos dados:
IDataView predictions = model.Transform(testingDataView); var metrics = mlContext.Regression.Evaluate(data:predictions, labelColumnName:"Label", scoreColumnName: "Score"); PrintRegressionMetrics(metrics);
Depois de treinar o nosso modelo precisamos saber o quão bem ele fará as previsões futuras? E com ML.NET você pode avaliar o seu modelo com novos dados de teste.
Cada tipo de tarefa de Machine Learning tem suas métricas utilizadas para avaliar a precisão e a exatidão do modelo em relação ao conjunto de dados de teste.
Para nosso exemplo de preço de residências, iremos usar um Algoritmo de Regressão. Dessa formar para avaliar o modelo vamos adicionar o código abaixo:
public static void PrintRegressionMetrics(RegressionMetrics metrics) { Console.WriteLine($"*************************************************"); Console.WriteLine($"* Metrics for Regression model "); Console.WriteLine($"*------------------------------------------------"); Console.WriteLine($"* LossFn: {metrics.LossFunction:0.##}"); Console.WriteLine($"* R2 Score: {metrics.RSquared:0.##}"); Console.WriteLine($"* Absolute loss: {metrics.MeanAbsoluteError:#.##}"); Console.WriteLine($"* Squared loss: {metrics.MeanSquaredError:#.##}"); Console.WriteLine($"* RMS loss: {metrics.RootMeanSquaredError:#.##}"); Console.WriteLine($"* RMS loss: {metrics.RootMeanSquaredError:#.##}"); Console.WriteLine($"*************************************************"); }
O código abaixo salva o Modelo em disco para que ele possa ser utilizado para previsões futuras sem a necessidade de realização de um novo treinamento:
mlContext.Model.Save(model, trainingDataView.Schema, modelPath);
Console.WriteLine(“O Modelo foi salvo em {0}”, modelPath);
O código abaixo carrega o Modelo do disco para que ele possa ser utilizado para nossas previsões:
ITransformer model = mlContext.Model.Load(modelPath, out var modelInputSchema); var predEngine = mlContext.Model.CreatePredictionEngine <ModelInput, ModelOutput>(model);
Por fim, vamos preencher um objeto do tipo ModelInput() para realizar uma previsão:
ModelInput sampleData = new ModelInput() { Longitude = -122.23F, Latitude = 37.88F, Housing_median_age = 41F, Total_rooms = 880F, Total_bedrooms = 129F, Population = 322F, Households = 126F, Median_income = 8.3252F, Ocean_proximity = @"NEAR BAY", };
E então, vemos o resultado da previsão:
var resultprediction = predEngine.Predict(sampleData); Console.WriteLine("Usando o modelo para fazer predição única - Comparando o valor atual de Median_house_value com o valor previsto de para os dados de amostra de Median_house_value ... \n \n"); Console.WriteLine($"Longitude: {sampleData.Longitude}"); Console.WriteLine($"Latitude: {sampleData.Latitude}"); Console.WriteLine($"Housing_median_age: {sampleData.Housing_median_age}"); Console.WriteLine($"Total_rooms: {sampleData.Total_rooms}"); Console.WriteLine($"Total_bedrooms: {sampleData.Total_bedrooms}"); Console.WriteLine($"Population: {sampleData.Population}"); Console.WriteLine($"Households: {sampleData.Households}"); Console.WriteLine($"Median_income: {sampleData.Median_income}"); Console.WriteLine($"Ocean_proximity: {sampleData.Ocean_proximity}"); Console.WriteLine ($"\n \nO Preço previsto para este tamanho é: {resultprediction.Score} \n \n"); Console.WriteLine ("=============== Fim do processo ===============");
O código do Projeto de exemplo e Análise Exploratória com ML.Net pode ser encontrado no meu github, assim como outros códigos sobre ML.Net.
Neste artigo nós percorremos todo o fluxo de uma Análise Exploratória de Dados (EDA) com ML.Net. Também podemos ver o seu uso em conjunto com um ambiente WSL (Ubuntu), demonstrando assim a capacidade deste framework multiplataforma. Lembre sempre que a Análise Exploratória é uma das etapas mais importantes nos projetos de Dados.
Portanto, no próximo artigo iremos disponibilizar o nosso modelo num aplicativo web.
Por fim, deixo algumas sugestões de conteúdos que você pode encontrar no Dados ao Cubo, sempre falando sobre o mundo dos dados.
Então, finalizo com um convite para você ser Parceiro de Publicação Dados ao Cubo e escrever o próximo artigo, compartilhando conhecimento para toda a comunidade de dados. Mas não esqueça de assinar a nossa Newsletter para ficar por dentro de todas as novidades.
Cientista de Dados especialista em Dados Jurídicos. 📊 Atuando como Data Product Manager na Softplan dedicado a projetos voltados para a aplicação da Ciência de Dados e Inteligência Artificial na área Jurídica. 📚 Atualmente tenho concentrado meus estudos em ML.Net o framework para Data Science da Microsoft.
Fala Galera do mundo dos dados, hora de manipular dados no MongoDB com Python. Dessa…
Fala Galera do mundo dos dados, hora de manipular dados no Cassandra com Python. Dessa…
Fala galera do mundo dos dados, hoje é dia de aprender a função Select do Spark.…
Fala galera do mundo dos dados, hoje é dia de transformar consultas SQL em visualizações…
Fala galera do mundo dos dados, dando continuidade às consultas de banco de dados com…
Fala galera do mundo dos dados, hora de conhecer os bancos de dados NoSQL com…