Distribuição normal e a classe Standard Scaler da biblioteca Scikit-learn em Python. Por que padronizar/normalizar os dados?

Matheus Vasconcelos
5 min readJul 24, 2023

--

Há alguns meses, estive estudando a disciplina de Probabilidade e Estatística na minha graduação em Engenharia de Telecomunicações, e notei finalmente o porquê de usar técnicas de Feature Engineering para padronização de dados, tais como Standard Scaler e normalizações com MinMax da biblioteca scikit-learn, etc.

A própria biblioteca scikit-learn, no tópico de Standard Scaler, já traz logo no começo uma introdução às razões dessa necessidade: “A padronização de um conjunto de dados é um requisito comum para muitos estimadores de aprendizado de máquina: eles podem se comportar mal se características individuais não se parecem mais ou menos com o padrão normalmente dados distribuídos.”

Mas do ponto de vista geral, padronizar dados significa ajustar a nossa distribuição de forma que encontremos um padrão nela, facilitando o entendimento do algoritmo num processo de Machine Learning, ou mesmo num processo estatístico manual. Padrões são o berço de todo cientista/matemático.

Distribuição Normal

Posso ilustrar isso com um exemplo que me fez entender de vez esse tópico: imagine que você tem aula às 10h todos os dias. A quantidade de pessoas que chega exatamente às 10h é grande, por exemplo, 30 pessoas. Se plotarmos um gráfico do fluxo de alunos nessa sala, obteremos exatamente às 10h um pico de alunos.

Note também que 10 minutos (09h50) antes do horário marcado (10h), sempre chegam alguns alunos adiantados, digamos 10 alunos (20 a menos que os que chegam no horário). Há também os mais esforçados que chegam 20 minutos (09h40) antes do horário marcado, digamos 5 pessoas.

Agora repitamos o processo só que de 10h pra frente. Chegariam também 10 alunos às 10h10, e também 5 alunos às 10h20.

Percebe o padrão aqui? Isso é um exemplo de distribuição normal. Há ainda várias outras situações em que esse tipo de processo aparece.

Perceba que o gráfico tem o exato formato descrito previamente, se traçarmos uma curva indo nas pontas de cada retângulo, teremos um sino, forma característica da distribuição normal.

Algumas características são:

  1. A curva da distribuição é simétrica em relação à sua média
  2. A área total sob a curva é de 100%
  3. Ela prolonga-se de -∞ à +∞
  4. Ela é especificada por uma média μ e um desvio padrão σ
  5. A distribuição tem um formato de sino
  6. Em uma distribuição normal, média = moda = mediana

Assim, se x é uma variável aleatória contínua que segue uma “N(μ, σ²) (que, traduzindo, significa distribuição contínua de média μ e variância σ²), a probabilidade P(a ≤ x ≤ b) é uma integral monstruosa que iremos deixar de lado num momento, pois precisamos apenas da tabela da distribuição normal.

Logo, para encontrarmos qualquer probabilidade intervalar de uma variável aleatória x ~ N(μ, σ²), podemos usar o score Z padronizado acima e a tabela da distribuição normal padrão, onde

Z = (x — μ) / σ

Exemplos de distribuição NÃO normal:

Salários numa empresa: a maior parte dos funcionários possuem um salário mais baixo, enquanto poucas pessoas ficam na cadeia de comando ganhando um salário elevado, portanto, o pico do gráfico sino da distribuição normal não existe aqui.

Exemplos de distribuição normal:

Notas de uma disciplina de dificuldade média: a maior parte das pessoas ficaria na média, que seria 7, enquanto alguns tirariam notas boas e uns poucos tirariam notas muito boas. Assim como alguns tirariam notas ruins e uns poucos tirariam notas muito ruins.

Standard Scaler

Quando aplicamos o StandardScaler aos dados, ele faz uso da distribuição normal e, portanto, transforma cada valor nos dados de forma que a média dos dados padronizados seja zero e o desvio padrão seja igual a um. Essa transformação garante que os dados estejam em uma escala comum, o que é útil para muitos algoritmos de aprendizado de máquina, especialmente aqueles que são sensíveis à escala dos atributos.

O objetivo de utilizar dessa distribuição para Machine Learning é de simplificar o processo de reconhecimento dos dados pela máquina evitando problemas como Bias (algoritmo enviesado), além de prevenir falhas de sobreajuste e subajuste (quando o modelo se ajusta demais aos dados e não generaliza bem futuros novos dados, ou quando ele não se ajusta bem aos dados, respectivamente)

Primeiro, importamos todas as bibliotecas necessárias. A visualização gráfia usando seaborn ou matplotlib é opcional, servindo apenas para ilustrar (e provar) que temos uma distribuição normal:

from sklearn.preprocessing import StandardScaler
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

Agora, vamos criar nossos dados usando pandas. (O gráfico que usei no início corresponde à essa tabela)

tabela = pd.DataFrame(
[('Nicolas Miqueias', 10),
('Cleiton Araújo', 10),
('Artur Martins', 10),
('Ernani Sousa', 10),
('Eduardo Gomes', 8),
('Guilherme Bastos', 8),
('Lucas Santos', 12),
('Larissa Santos', 12),
('Lia Souza', 6),
('Rafael Peres', 14)],
columns=('nome', 'horário'))

Lembrando o ponto 6, podemos provar ainda que essa distribuição é normal usando o np.mean(), np.mode()[0] e np.median(). Ou seja, simplesmente, verificamos a média, moda e mediana, e veremos que são iguais

np.median(tabela['horário']) == tabela['horário'].mean() == tabela['horário'].mode()[0]
>>> True

Finalmente, vamos usar o Standard Scaler. Bom lembrar que o método fit e transform esperam um array 2D, ou seja dados bidimensionais, então devemos usar os dois colchetes em cada ponta:

tabela['horário'] #ERRADO
tabela[['horário']] #CERTO
scaler = StandardScaler() #Criamos a função scaler
print(scaler.fit(tabela[['horário']])) #Fazemos o fit dos dados (2D)
print(scaler.transform(tabela[['horário']])) #Transfomamos os dados para distribuição normal

>>> StandardScaler()

[[ 0. ]
[ 0. ]
[ 0. ]
[ 0. ]
[-0.91287093]
[-0.91287093]
[ 0.91287093]
[ 0.91287093]
[-1.82574186]
[ 1.82574186]]

Finalizado! Essa matriz gerada no final é a matriz com os dados padronizados, de média 0 e desvio padrão 1.

O notebook utilizado pra esse post é bem simples, e segue basicamente o exemplo da documentação, e boa parte dele já resumi aqui, mas à título de curiosidade, segue o código com alguns recursos extras como os gráficos:

Standard Scaler.ipynb — Colaboratory (google.com)

--

--

Matheus Vasconcelos

Portfolio: https://www.kaggle.com/mhvasconcelos A Telecommunications Engineering student, passionate about science, programming, and data analysis.