PySpark Tutorial para Iniciantes: Aprenda com EXEMPLOS

โšก Resumo Inteligente

PySpark รฉ o Python API para Apache Spark, permitindo que analistas executem processamento de dados distribuรญdo, consultas SQL e aprendizado de mรกquina em clusters. Este passo a passo instala e explica como. SparkO Contexto e o SQLContext sรฃo utilizados para construir um classificador de regressรฃo logรญstica.

  • ๐Ÿ”˜ Noรงรตes bรกsicas de motor: Spark Programa, distribui e monitora o trabalho em um conjunto de mรกquinas de trabalho, mantendo-as sempre atualizadas.ping Computaรงรฃo na memรณria.
  • โ˜‘๏ธ Python ponte: PySpark expรตe RDDs, DataFrames e MLlib para Python, permitindo que os usuรกrios do pandas ultrapassem os limites de uma รบnica mรกquina.
  • โœ… Duas opรงรตes de instalaรงรฃo: Uma imagem Docker em uma instรขncia AWS ou um ambiente conda dedicado em Windows e Mac.
  • ๐Ÿงช Pontos de entrada: SparkO contexto abre a conexรฃo com o cluster; SQLContext (SparkA sessรฃo (em versรตes modernas) cria DataFrames a partir de arquivos.
  • ๐Ÿ› ๏ธ API de Pipeline: Os estรกgios StringIndexer, OneHotEncoder e VectorAssembler montam recursos exatamente da mesma forma que os pipelines do scikit-learn.
  • ๐Ÿ“Š Recompensaรงรฃo do ajuste: A validaรงรฃo cruzada do parรขmetro de regularizaรงรฃo eleva a precisรฃo do classificador do conjunto de dados de adultos de 82.376% para 85.316%.

PySpark Tutorial para iniciantes

Antes de aprender PySpark, vamos entender:

o que รฉ apache Spark?

Spark รฉ uma soluรงรฃo de big data comprovadamente mais fรกcil e rรกpida que o Hadoop MapReduce. Spark รฉ um software de cรณdigo aberto desenvolvido pelo laboratรณrio UC Berkeley RAD em 2009. Desde que foi lanรงado ao pรบblico em 2010, Spark cresceu em popularidade e รฉ usado na indรบstria em uma escala sem precedentes.

Na era do Big Data, os profissionais precisam, mais do que nunca, de ferramentas rรกpidas e confiรกveis โ€‹โ€‹para processar fluxos de dados. Ferramentas anteriores, como o MapReduce, eram as preferidas, mas lentas. Para superar esse problema, Spark oferece uma soluรงรฃo rรกpida e de uso geral. A principal diferenรงa entre Spark e MapReduce รฉ isso Spark executa cรกlculos na memรณria durante o รบltimo no disco rรญgido. Ele permite acesso e processamento de dados em alta velocidade, reduzindo os tempos de horas para minutos.

O que รฉ PiSpark?

PySpark รฉ uma ferramenta criada pelo Apache Spark Comunidade para uso Python com as Spark. Permite trabalhar com RDD (Resilient Distributed Dataset) em Python. Tambรฉm oferece PySpark Shell para vincular Python APIs com Spark nรบcleo para iniciar Spark Contexto. Spark รฉ o mecanismo de nome para realizar a computaรงรฃo em cluster, enquanto PySpark is Pythonbiblioteca para usar Spark.

A biblioteca รฉ enviada como a pyspark pacote no PyPI, portanto, um รบnico pip install pyspark utiliza o mecanismo Scala/JVM mais a ponte Py4J que permite Python Os objetos fazem chamadas a ele. Tudo o que vem depois se baseia nesse pacote.

Como funciona Spark funciona?

Spark ร‰ baseado em um mecanismo computacional, o que significa que ele cuida do agendamento, distribuiรงรฃo e monitoramento da aplicaรงรฃo. Cada tarefa รฉ executada em vรกrias mรกquinas de trabalho, chamadas de clusters de computaรงรฃo. Um cluster de computaรงรฃo se refere ร  divisรฃo de tarefas. Uma mรกquina executa uma tarefa, enquanto as outras contribuem para o resultado final por meio de uma tarefa diferente. No final, todas as tarefas sรฃo agregadas para produzir um resultado. Spark administrador fornece uma visรฃo geral 360ยบ de vรกrios Spark Empregos.

O diagrama abaixo mostra como um programa de driver delega tarefas ร s mรกquinas trabalhadoras que compรตem esse cluster.

Spark cluster de computaรงรฃo mostrando o agendamento de tarefas do driver em mรกquinas de trabalho

Como a Spark Cases

Spark foi projetado para trabalhar com

  • Python
  • Java
  • Scala
  • SQL

Uma caracterรญstica significativa Spark รฉ a vasta quantidade de bibliotecas integradas, incluindo o MLlib para aprendizado de mรกquina. Spark Ele tambรฉm foi projetado para funcionar com clusters Hadoop e pode ler uma ampla variedade de arquivos, incluindo dados Hive, CSV, JSON, Cassandra dados entre outros.

Por que usar Spark?

Como futuro profissional de dados, vocรช deve estar familiarizado com PythonBibliotecas famosas de: Pandas e scikit-learnEssas duas bibliotecas sรฃo fantรกsticas para explorar conjuntos de dados de atรฉ tamanho mรฉdio. Projetos comuns de aprendizado de mรกquina sรฃo construรญdos em torno da seguinte metodologia:

  • Carregue os dados no disco
  • Importe os dados para a memรณria da mรกquina
  • Processar/analisar os dados
  • Construa o modelo de aprendizado de mรกquina
  • Armazene a previsรฃo de volta no disco

O problema surge quando o cientista de dados precisa processar um volume de dados muito grande para um รบnico computador. No inรญcio da ciรชncia de dados, os profissionais realizavam amostragens, jรก que o treinamento com conjuntos de dados enormes nem sempre era necessรกrio. O cientista de dados encontrava uma boa amostra estatรญstica, realizava uma verificaรงรฃo de robustez adicional e obtinha um excelente modelo.

No entanto, existem alguns problemas com isso:

  • O conjunto de dados reflete o mundo real?
  • Os dados incluem um exemplo especรญfico?
  • O modelo รฉ adequado para amostragem?

Veja a recomendaรงรฃo dos usuรกrios, por exemplo. Os recomendadores baseiam-se na comparaรงรฃo de usuรกrios com outros usuรกrios para avaliar suas preferรชncias. Se o profissional de dados obtiver apenas um subconjunto dos dados, nรฃo haverรก um grupo de usuรกrios muito semelhantes entre si. Os recomendadores precisam ser executados no conjunto de dados completo ou nรฃo.

Qual รฉ a soluรงรฃo?

A soluรงรฃo jรก รฉ evidente hรก muito tempo: dividir o problema em vรกrios computadores. A computaรงรฃo paralela tambรฉm apresenta vรกrios problemas. Os desenvolvedores geralmente tรชm problemas para escrever cรณdigo paralelo e acabam tendo que resolver vรกrios problemas complexos relacionados ao prรณprio multiprocessamento.

PySpark Fornece ao cientista de dados uma API que pode ser usada para resolver problemas de processamento paralelo de dados. PySpark Lida com as complexidades do multiprocessamento, como a distribuiรงรฃo de dados, a distribuiรงรฃo de cรณdigo e a coleta da saรญda dos trabalhadores em um cluster de mรกquinas.

Spark pode ser executado de forma independente, mas na maioria das vezes รฉ executado em uma estrutura de computaรงรฃo em cluster, como o Hadoop. No entanto, em teste e desenvolvimento, um cientista de dados pode executar com eficiรชncia Spark em suas caixas de desenvolvimento ou laptops sem um cluster

  • Uma das principais vantagens de Spark รฉ construir uma arquitetura que abrange gerenciamento de streaming de dados, consultas de dados integradas, previsรฃo de aprendizado de mรกquina e acesso em tempo real a diversas anรกlises.
  • Spark trabalha em estreita colaboraรงรฃo com SQL linguagem, ou seja, dados estruturados. Permite consultar os dados em tempo real.
  • A principal funรงรฃo de um cientista de dados รฉ analisar e construir modelos preditivos. Em resumo, um cientista de dados precisa saber como consultar dados usando SQL, produzir relatรณrios estatรญsticos e utilizar aprendizado de mรกquina para gerar previsรตes. O cientista de dados dedica uma parte significativa do seu tempo ร  limpeza, transformaรงรฃo e anรกlise dos dados. Uma vez que o conjunto de dados ou o fluxo de trabalho de dados esteja pronto, o cientista de dados utiliza diversas tรฉcnicas para descobrir insights e padrรตes ocultos. A manipulaรงรฃo dos dados deve ser robusta e, ao mesmo tempo, fรกcil de usar. Spark รฉ a ferramenta certa graรงas ร  sua velocidade e APIs ricas.

Neste PySpark tutorial, vocรช aprenderรก como construir um classificador com PySpark exemplos.

Como instalar o PySpark com AWS

O Jupyter equipe constrรณi uma imagem Docker para executar Spark eficientemente. Abaixo estรฃo as etapas que vocรช pode seguir para instalar o PySpark instรขncia na AWS.

Consulte nosso tutorial em AWS e TensorFlow

Etapa 1: crie uma instรขncia

Primeiro de tudo, vocรช precisa criar uma instรขncia. Acesse sua conta AWS e execute a instรขncia. Vocรช pode aumentar o armazenamento em atรฉ 15g e usar o mesmo grupo de seguranรงa do tutorial do TensorFlow.

Passo 2: Abra a conexรฃo

Abra a conexรฃo e instale o contรชiner docker. Para obter mais detalhes, consulte o tutorial com TensorFlow com Estivador. Observe que vocรช precisa estar no diretรณrio de trabalho correto.

Basta executar estes cรณdigos para instalar o Docker:

sudo yum update -y
sudo yum install -y docker
sudo service docker start
sudo user-mod -a -G docker ec2-user
exit

Etapa 3: reabra a conexรฃo e instale Spark

Depois de reabrir a conexรฃo, vocรช pode instalar a imagem contendo PySpark.

## Spark
docker run -v ~/work:/home/jovyan/work -d -p 8888:8888 jupyter/pyspark-notebook

## Allow preserving Jupyter notebook
sudo chown 1000 ~/work

## Install tree to see our working directory next
sudo yum install -y tree

Etapa 4: Abrir Jupyter

Verifique o contรชiner e seu nome

docker ps

Inicie a janela de encaixe com os logs da janela de encaixe seguidos do nome da janela de encaixe. Por exemplo, docker registra zealous_goldwasser

Vรก para o seu navegador e inicie Jupyter. O endereรงo รฉ http://localhost:8888/. Cole a senha fornecida pelo terminal.

Observaรงรฃo: Se vocรช deseja enviar/baixar um arquivo para sua mรกquina AWS, pode usar o software. Cyberduck.

Como instalar o PySpark on Windows/Mac com Conda

A seguir estรก um processo detalhado sobre como instalar o PySpark on Windows/Mac usando Anaconda:

Para instalar Spark na sua mรกquina local, uma prรกtica recomendada รฉ criar um novo ambiente conda. Este novo ambiente irรก instalar Python 3.6, Spark e todas as dependรชncias.

Usuรกrio Mac

cd anaconda3
touch hello-spark.yml
vi hello-spark.yml

Windows Utilizador

cd C:\Users\Admin\Anaconda3
echo.>hello-spark.yml
notepad hello-spark.yml

Vocรช pode editar o arquivo .yml. Tenha cuidado com o recuo. Dois espaรงos sรฃo necessรกrios antes -

name: hello-spark 
    dependencies:
    
    - python=3.6
    - jupyter
    - ipython
    - numpy
    - numpy-base
    - pandas
    - py4j
    - pyspark
    - pytz

Salve-o e crie o ambiente. Isso leva algum tempo

conda env create -f hello-spark.yml

Para mais detalhes sobre a localizaรงรฃo, consulte o tutorial Instalar TensorFlow

Vocรช pode verificar todo o ambiente instalado em sua mรกquina

conda env list
Activate hello-spark

Usuรกrio Mac

source activate hello-spark

Windows Utilizador

activate hello-spark

Observaรงรฃo: Vocรช jรก criou um ambiente especรญfico do TensorFlow para executar os tutoriais no TensorFlow. ร‰ mais conveniente criar um novo ambiente diferente do hello-tf. Nรฃo faz sentido sobrecarregar o hello-tf com Spark ou qualquer outra biblioteca de aprendizado de mรกquina.

Imagine que a maior parte do seu projeto envolve o TensorFlow, mas vocรช precisa usar Spark para um projeto especรญfico. Vocรช pode definir um ambiente TensorFlow para todo o seu projeto e criar um ambiente separado para Spark. Vocรช pode adicionar quantas bibliotecas em Spark ambiente como desejar, sem interferir no ambiente do TensorFlow. Assim que terminar com o Sparkdo projeto, vocรช pode apagรก-lo sem afetar o ambiente do TensorFlow.

Jupyter

Abra Jupyter Notebook e tente se PySpark funciona. Em um novo caderno cole o seguinte PySpark Cรณdigo de amostra:

import pyspark
from pyspark import SparkContext
sc =SparkContext()

Uma execuรงรฃo bem-sucedida nรฃo imprime nenhuma saรญda, como mostra a captura de tela do notebook abaixo.

Jupyter Cรฉlula do notebook importando pyspark e criando um SparkObjeto de contexto

Se um erro for mostrado, รฉ provรกvel que Java nรฃo estรก instalado na sua mรกquina. No mac, abra o terminal e escreva java -version, se houver uma versรฃo do java, certifique-se de que seja 1.8. Em Windows, acesse Aplicativo e verifique se existe um Java pasta. Se houver um Java pasta, verifique isso Java A versรฃo 1.8 estรก instalada. Atรฉ o momento desta publicaรงรฃo, PySpark nรฃo รฉ compatรญvel com Java 9 e acima.

Nota de versรฃo: que. Java A restriรงรฃo 8 aplica-se ao Spark A versรฃo 2.x รฉ utilizada ao longo deste passo a passo. Atual Spark As versรตes 3.x e 4.x funcionam em Java 8, 11 e 17, entรฃo um JDK mais recente funciona bem se vocรช instalar um Py compatรญvel.Spark versรฃo.

Se vocรช precisar instalar Java, vocรช pensa link e baixe jdk-8u181-windows-x64.exe

Para usuรกrios de Mac, รฉ recomendado usar `brew.`

brew tap caskroom/versions
brew cask install java8

Consulte este tutorial passo a passo em como instalar Java

Observaรงรฃo: Use a opรงรฃo "Remover" para apagar completamente um ambiente.

 conda env remove -n hello-spark -y

Spark contexto

SparkContexto รฉ o mecanismo interno que permite as conexรตes com os clusters. Se vocรช deseja executar uma operaรงรฃo, vocรช precisa de um SparkContexto.

Crie uma Sparkcontexto

Primeiro de tudo, vocรช precisa iniciar um SparkContexto.

import pyspark
from pyspark import SparkContext
sc =SparkContext()

Agora que o SparkO contexto estรก pronto, vocรช pode criar uma coleรงรฃo de dados chamada RDD, Resilient Distributed Dataset. A computaรงรฃo em um RDD รฉ automaticamente paralelizada em todo o cluster.

nums= sc.parallelize([1,2,3,4])

Vocรช pode acessar a primeira linha com take

nums.take(1)
[1]

Vocรช pode aplicar uma transformaรงรฃo aos dados com uma funรงรฃo lambda. No PySpark exemplo abaixo, vocรช retorna o quadrado de nums. ร‰ uma transformaรงรฃo de mapa

squared = nums.map(lambda x: x*x).collect()
for num in squared:
    print('%i ' % (num))
1 
4 
9 
16

SQLContexto

Uma maneira mais conveniente รฉ usar o DataFrame. SparkO contexto jรก estรก definido; vocรช pode usรก-lo para criar o DataFrame. Vocรช tambรฉm precisa declarar o SQLContext.

SQLContext permite conectar o mecanismo com diferentes fontes de dados. ร‰ usado para iniciar as funcionalidades do Spark SQL

Nota de versรฃo: SQLContext foi substituรญdo por SparkSessรฃo em Spark 2.0 e formalmente descontinuado em Spark 3.0. Os exemplos abaixo mantรชm o SQLContext porque รฉ nele que o passo a passo original รฉ executado; em um cluster moderno, o ponto de entrada equivalente รฉ SparkSession.builder.getOrCreate(), que expรตe os mesmos mรฉtodos read e createDataFrame.

from pyspark.sql import Row
from pyspark.sql import SQLContext

sqlContext = SQLContext(sc)

Agora neste Spark tutorial Python, vamos criar uma lista de tuplas. Cada tupla conterรก o nome das pessoas e sua idade. Sรฃo necessรกrias quatro etapas:

Passo 1) Crie a lista de tupla com as informaรงรตes

[('John',19),('Smith',29),('Adam',35),('Henry',50)]

Passo 2) Construa um RDD

rdd = sc.parallelize(list_p)

Passo 3) Converta as tuplas

rdd.map(lambda x: Row(name=x[0], age=int(x[1])))

Passo 4) Crie um contexto DataFrame

sqlContext.createDataFrame(ppl)
list_p = [('John',19),('Smith',29),('Adam',35),('Henry',50)]
rdd = sc.parallelize(list_p)
ppl = rdd.map(lambda x: Row(name=x[0], age=int(x[1])))
DF_ppl = sqlContext.createDataFrame(ppl)

Se quiser acessar o tipo de cada recurso, vocรช pode usar printSchema()

DF_ppl.printSchema()
root
 |-- age: long (nullable = true)
 |-- name: string (nullable = true)

Exemplo de aprendizado de mรกquina com PySpark

Agora que vocรช tem uma breve ideia Spark e SQLContext, vocรช estรก pronto para criar seu primeiro programa de aprendizado de mรกquina.

A seguir estรฃo as etapas para construir um programa de aprendizado de mรกquina com PySpark:

  • Etapa 1) Operaรงรฃo bรกsica com PySpark
  • Etapa 2) Prรฉ-processamento de dados
  • Etapa 3) Construir um pipeline de processamento de dados
  • Etapa 4) Construa o classificador: logรญstico
  • Etapa 5) Treine e avalie o modelo
  • Etapa 6) Ajustar o hiperparรขmetro

Neste PySpark Neste tutorial de Machine Learning, usaremos o conjunto de dados de adultos. O objetivo deste tutorial รฉ aprender a usar o Python.SparkPara obter mais informaรงรตes sobre o conjunto de dados, consulte este tutorial.

Observe que o conjunto de dados nรฃo รฉ significativo e vocรช pode pensar que o cรกlculo demora muito. Spark foi projetado para processar uma quantidade considerรกvel de dados. SparkO desempenho do [nome da biblioteca] aumenta em relaรงรฃo a outras bibliotecas de aprendizado de mรกquina quando o conjunto de dados processado cresce.

Etapa 1) Operaรงรฃo bรกsica com PySpark

Primeiro de tudo, vocรช precisa inicializar o SQLContext que ainda nรฃo foi iniciado.

#from pyspark.sql import SQLContext
url = "https://raw.githubusercontent.com/guru99-edu/R-Programming/master/adult_data.csv"
from pyspark import SparkFiles
sc.addFile(url)
sqlContext = SQLContext(sc)

entรฃo, vocรช pode ler o arquivo cvs com sqlContext.read.csv. Vocรช usa inferSchema definido como True para informar Spark adivinhar automaticamente o tipo de dados. Por padrรฃo, รฉ alterado para False.

df = sqlContext.read.csv(SparkFiles.get("adult_data.csv"), header=True, inferSchema= True)

Vamos dar uma olhada no tipo de dados

df.printSchema()
root
 |-- age: integer (nullable = true)
 |-- workclass: string (nullable = true)
 |-- fnlwgt: integer (nullable = true)
 |-- education: string (nullable = true)
 |-- education_num: integer (nullable = true)
 |-- marital: string (nullable = true)
 |-- occupation: string (nullable = true)
 |-- relationship: string (nullable = true)
 |-- race: string (nullable = true)
 |-- sex: string (nullable = true)
 |-- capital_gain: integer (nullable = true)
 |-- capital_loss: integer (nullable = true)
 |-- hours_week: integer (nullable = true)
 |-- native_country: string (nullable = true)
 |-- label: string (nullable = true)

Vocรช pode ver os dados com show.

df.show(5, truncate = False)
+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+----------+--------------+-----+
|age|workclass       |fnlwgt|education|education_num|marital           |occupation       |relationship |race |sex   |capital_gain|capital_loss|hours_week|native_country|label|
+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+----------+--------------+-----+
|39 |State-gov       |77516 |Bachelors|13           |Never-married     |Adm-clerical     |Not-in-family|White|Male  |2174        |0           |40        |United-States |<=50K|
|50 |Self-emp-not-inc|83311 |Bachelors|13           |Married-civ-spouse|Exec-managerial  |Husband      |White|Male  |0           |0           |13        |United-States |<=50K|
|38 |Private         |215646|HS-grad  |9            |Divorced          |Handlers-cleaners|Not-in-family|White|Male  |0           |0           |40        |United-States |<=50K|
|53 |Private         |234721|11th     |7            |Married-civ-spouse|Handlers-cleaners|Husband      |Black|Male  |0           |0           |40        |United-States |<=50K|
|28 |Private         |338409|Bachelors|13           |Married-civ-spouse|Prof-specialty   |Wife         |Black|Female|0           |0           |40        |Cuba          |<=50K|
+---+----------------+------+---------+-------------+------------------+-----------------+-------------+-----+------+------------+------------+----------+--------------+-----+
only showing top 5 rows

Se vocรช nรฃo definiu `inferSchema` como `True`, eis o que acontece com o tipo. Todos os valores sรฃo do tipo string.

df_string = sqlContext.read.csv(SparkFiles.get("adult.csv"), header=True, inferSchema=  False)
df_string.printSchema()
root
 |-- age: string (nullable = true)
 |-- workclass: string (nullable = true)
 |-- fnlwgt: string (nullable = true)
 |-- education: string (nullable = true)
 |-- education_num: string (nullable = true)
 |-- marital: string (nullable = true)
 |-- occupation: string (nullable = true)
 |-- relationship: string (nullable = true)
 |-- race: string (nullable = true)
 |-- sex: string (nullable = true)
 |-- capital_gain: string (nullable = true)
 |-- capital_loss: string (nullable = true)
 |-- hours_week: string (nullable = true)
 |-- native_country: string (nullable = true)
 |-- label: string (nullable = true)

Para converter a variรกvel contรญnua no formato correto, vocรช pode usar a reformulaรงรฃo das colunas. Vocรช pode usar withColumn para contar Spark qual coluna operar a transformaรงรฃo.

# Import all from `sql.types`
from pyspark.sql.types import *

# Write a custom function to convert the data type of DataFrame columns
def convertColumn(df, names, newType):
    for name in names: 
        df = df.withColumn(name, df[name].cast(newType))
    return df 
# List of continuous features
CONTI_FEATURES  = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week']
# Convert the type
df_string = convertColumn(df_string, CONTI_FEATURES, FloatType())
# Check the dataset
df_string.printSchema()
root
 |-- age: float (nullable = true)
 |-- workclass: string (nullable = true)
 |-- fnlwgt: float (nullable = true)
 |-- education: string (nullable = true)
 |-- education_num: float (nullable = true)
 |-- marital: string (nullable = true)
 |-- occupation: string (nullable = true)
 |-- relationship: string (nullable = true)
 |-- race: string (nullable = true)
 |-- sex: string (nullable = true)
 |-- capital_gain: float (nullable = true)
 |-- capital_loss: float (nullable = true)
 |-- hours_week: float (nullable = true)
 |-- native_country: string (nullable = true)
 |-- label: string (nullable = true)

from pyspark.ml.feature import StringIndexer
#stringIndexer = StringIndexer(inputCol="label", outputCol="newlabel")
#model = stringIndexer.fit(df)
#df = model.transform(df)
df.printSchema()

Selecionar colunas

Vocรช pode selecionar e mostrar as linhas com select e os nomes dos recursos. Abaixo, idade e fnlwgt estรฃo selecionados.

df.select('age','fnlwgt').show(5)
+---+------+
|age|fnlwgt|
+---+------+
| 39| 77516|
| 50| 83311|
| 38|215646|
| 53|234721|
| 28|338409|
+---+------+
only showing top 5 rows

Contar por grupo

Se vocรช quiser contar o nรบmero de ocorrรชncias por grupo, pode encadear:

  • grupoBy()
  • contagem()

junto. No PySpark exemplo abaixo, vocรช conta o nรบmero de linhas pelo nรญvel de escolaridade.

df.groupBy("education").count().sort("count",ascending=True).show()
+------------+-----+
|   education|count|
+------------+-----+
|   Preschool|   51|
|     1st-4th|  168|
|     5th-6th|  333|
|   Doctorate|  413|
|        12th|  433|
|         9th|  514|
| Prof-school|  576|
|     7th-8th|  646|
|        10th|  933|
|  Assoc-acdm| 1067|
|        11th| 1175|
|   Assoc-voc| 1382|
|     Masters| 1723|
|   Bachelors| 5355|
|Some-college| 7291|
|     HS-grad|10501|
+------------+-----+

Descreva os dados

Para obter estatรญsticas resumidas dos dados, vocรช pode usar description(). Ele irรก calcular:

  • contar
  • significar
  • desvio padrรฃo
  • min
  • max
df.describe().show()
+-------+------------------+-----------+------------------+------------+-----------------+--------+----------------+------------+------------------+------+------------------+----------------+------------------+--------------+-----+
|summary|               age|  workclass|            fnlwgt|   education|    education_num| marital|      occupation|relationship|              race|   sex|      capital_gain|    capital_loss|        hours_week|native_country|label|
+-------+------------------+-----------+------------------+------------+-----------------+--------+----------------+------------+------------------+------+------------------+----------------+------------------+--------------+-----+
|  count|             32561|      32561|             32561|       32561|            32561|   32561|           32561|       32561|             32561| 32561|             32561|           32561|             32561|         32561|32561|
|   mean| 38.58164675532078|       null|189778.36651208502|        null| 10.0806793403151|    null|            null|        null|              null|  null|1077.6488437087312| 87.303829734959|40.437455852092995|          null| null|
| stddev|13.640432553581356|       null|105549.97769702227|        null|2.572720332067397|    null|            null|        null|              null|  null| 7385.292084840354|402.960218649002|12.347428681731838|          null| null|
|    min|                17|          ?|             12285|        10th|                1|Divorced|               ?|     Husband|Amer-Indian-Eskimo|Female|                 0|               0|                 1|             ?|<=50K|
|    max|                90|Without-pay|           1484705|Some-college|               16| Widowed|Transport-moving|        Wife|             White|  Male|             99999|            4356|                99|    Yugoslavia| >50K|
+-------+------------------+-----------+------------------+------------+-----------------+--------+----------------+------------+------------------+------+------------------+----------------+------------------+--------------+-----+

Se vocรช deseja a estatรญstica resumida de apenas uma coluna, adicione o nome da coluna dentro describe()

df.describe('capital_gain').show()
+-------+------------------+
|summary|      capital_gain|
+-------+------------------+
|  count|             32561|
|   mean|1077.6488437087312|
| stddev| 7385.292084840354|
|    min|                 0|
|    max|             99999|
+-------+------------------+

Cรกlculo de tabela cruzada

Em algumas ocasiรตes, pode ser interessante ver as estatรญsticas descritivas entre duas colunas emparelhadas. Por exemplo, vocรช pode contar o nรบmero de pessoas com renda abaixo ou acima de 50 mil por nรญvel de escolaridade. Esta operaรงรฃo รฉ chamada de crosstab.

df.crosstab('age', 'label').sort("age_label").show()
+---------+-----+----+
|age_label|<=50K|>50K|
+---------+-----+----+
|       17|  395|   0|
|       18|  550|   0|
|       19|  710|   2|
|       20|  753|   0|
|       21|  717|   3|
|       22|  752|  13|
|       23|  865|  12|
|       24|  767|  31|
|       25|  788|  53|
|       26|  722|  63|
|       27|  754|  81|
|       28|  748| 119|
|       29|  679| 134|
|       30|  690| 171|
|       31|  705| 183|
|       32|  639| 189|
|       33|  684| 191|
|       34|  643| 243|
|       35|  659| 217|
|       36|  635| 263|
+---------+-----+----+
only showing top 20 rows

Vocรช pode ver que nenhuma pessoa tem receita acima de 50 mil quando รฉ jovem.

Coluna de queda

Existem duas APIs intuitivas para eliminar colunas:

  • drop(): descarta uma coluna
  • dropna(): Elimina NA's

Abaixo vocรช solta a coluna education_num

df.drop('education_num').columns

['age',
 'workclass',
 'fnlwgt',
 'education',
 'marital',
 'occupation',
 'relationship',
 'race',
 'sex',
 'capital_gain',
 'capital_loss',
 'hours_week',
 'native_country',
 'label']

Dados de filtro

Vocรช pode usar filter() para aplicar estatรญsticas descritivas em um subconjunto de dados. Por exemplo, vocรช pode contar o nรบmero de pessoas com mais de 40 anos

df.filter(df.age > 40).count()

13443

Descriptcinco estatรญsticas por grupo

Finalmente, vocรช pode agrupar dados por grupo e calcular operaรงรตes estatรญsticas como a mรฉdia.

df.groupby('marital').agg({'capital_gain': 'mean'}).show()
+--------------------+------------------+
|             marital| avg(capital_gain)|
+--------------------+------------------+
|           Separated| 535.5687804878049|
|       Never-married|376.58831788823363|
|Married-spouse-ab...| 653.9832535885167|
|            Divorced| 728.4148098131893|
|             Widowed| 571.0715005035247|
|   Married-AF-spouse| 432.6521739130435|
|  Married-civ-spouse|1764.8595085470085|
+--------------------+------------------+

Etapa 2) Prรฉ-processamento de dados

O processamento de dados รฉ uma etapa crรญtica no aprendizado de mรกquina. Depois de remover dados inรบteis, vocรช obtรฉm alguns insights importantes.

Por exemplo, vocรช sabe que a idade nรฃo รฉ uma funรงรฃo linear com a renda. Quando as pessoas sรฃo jovens, o seu rendimento รฉ geralmente inferior ao da meia-idade. Apรณs a reforma, o agregado familiar utiliza as suas poupanรงas, o que significa uma diminuiรงรฃo do rendimento. Para capturar esse padrรฃo, vocรช pode adicionar um quadrado ao recurso de idade

Adicionar quadrado de idade

Para adicionar um novo recurso, vocรช precisa:

  1. Selecione a coluna
  2. Aplique a transformaรงรฃo e adicione-a ao DataFrame
from pyspark.sql.functions import *

# 1 Select the column
age_square = df.select(col("age")**2)

# 2 Apply the transformation and add it to the DataFrame
df = df.withColumn("age_square", col("age")**2)

df.printSchema()
root
 |-- age: integer (nullable = true)
 |-- workclass: string (nullable = true)
 |-- fnlwgt: integer (nullable = true)
 |-- education: string (nullable = true)
 |-- education_num: integer (nullable = true)
 |-- marital: string (nullable = true)
 |-- occupation: string (nullable = true)
 |-- relationship: string (nullable = true)
 |-- race: string (nullable = true)
 |-- sex: string (nullable = true)
 |-- capital_gain: integer (nullable = true)
 |-- capital_loss: integer (nullable = true)
 |-- hours_week: integer (nullable = true)
 |-- native_country: string (nullable = true)
 |-- label: string (nullable = true)
 |-- age_square: double (nullable = true)

Vocรช pode ver que age_square foi adicionado com sucesso ao quadro de dados. Vocรช pode alterar a ordem das variรกveis โ€‹โ€‹com select. Abaixo, vocรช traz age_square logo apรณs age.

COLUMNS = ['age', 'age_square', 'workclass', 'fnlwgt', 'education', 'education_num', 'marital',
           'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss',
           'hours_week', 'native_country', 'label']
df = df.select(COLUMNS)
df.first()
Row(age=39, age_square=1521.0, workclass='State-gov', fnlwgt=77516, education='Bachelors', education_num=13, marital='Never-married', occupation='Adm-clerical', relationship='Not-in-family', race='White', sex='Male', capital_gain=2174, capital_loss=0, hours_week=40, native_country='United-States', label='<=50K')

Excluir Holanda-Holanda

Quando um grupo dentro de um recurso possui apenas uma observaรงรฃo, ele nรฃo traz nenhuma informaรงรฃo para o modelo. Pelo contrรกrio, pode levar a um erro durante a validaรงรฃo cruzada.

Vamos verificar a origem do agregado familiar

df.filter(df.native_country == 'Holand-Netherlands').count()
df.groupby('native_country').agg({'native_country': 'count'}).sort(asc("count(native_country)")).show()
+--------------------+---------------------+
|      native_country|count(native_country)|
+--------------------+---------------------+
|  Holand-Netherlands|                    1|
|            Scotland|                   12|
|             Hungary|                   13|
|            Honduras|                   13|
|Outlying-US(Guam-...|                   14|
|          Yugoslavia|                   16|
|            Thailand|                   18|
|                Laos|                   18|
|            Cambodia|                   19|
|     Trinadad&Tobago|                   19|
|                Hong|                   20|
|             Ireland|                   24|
|             Ecuador|                   28|
|              Greece|                   29|
|              France|                   29|
|                Peru|                   31|
|           Nicaragua|                   34|
|            Portugal|                   37|
|                Iran|                   43|
|               Haiti|                   44|
+--------------------+---------------------+
only showing top 20 rows

O recurso native_country possui apenas um domicรญlio vindo da Holanda. Vocรช exclui isso.

df_remove = df.filter(df.native_country !=	'Holand-Netherlands')

Etapa 3) Construir um pipeline de processamento de dados

Semelhante ao scikit-learn, PySpark Possui uma API de pipeline.

Um pipeline รฉ muito conveniente para manter a estrutura dos dados. Vocรช envia os dados para o pipeline. Dentro do pipeline, diversas operaรงรตes sรฃo realizadas, a saรญda รฉ usada para alimentar o algoritmo.

Por exemplo, uma transformaรงรฃo universal em aprendizado de mรกquina consiste em converter uma string em um codificador ativo, ou seja, uma coluna por grupo. Um codificador ativo geralmente รฉ uma matriz cheia de zeros.

As etapas para transformar os dados sรฃo muito semelhantes ร s do scikit-learn. Vocรช precisa:

  • Indexar a string para numรฉrico
  • Crie o รบnico codificador ativo
  • Transforme os dados

Duas APIs fazem o trabalho: StringIndexer, OneHotEncoder

  1. Primeiro de tudo, vocรช seleciona a coluna de string a ser indexada. O inputCol รฉ o nome da coluna no conjunto de dados. outputCol รฉ o novo nome dado ร  coluna transformada.
StringIndexer(inputCol="workclass", outputCol="workclass_encoded")
  1. Ajuste os dados e transforme-os
model = stringIndexer.fit(df)		
`indexed = model.transform(df)``
  1. Crie as colunas de notรญcias com base no grupo. Por exemplo, se houver 10 grupos no recurso, a nova matriz terรก 10 colunas, uma para cada grupo.
OneHotEncoder(dropLast=False, inputCol="workclassencoded", outputCol="workclassvec")
### Example encoder
from pyspark.ml.feature import StringIndexer, OneHotEncoder, VectorAssembler

stringIndexer = StringIndexer(inputCol="workclass", outputCol="workclass_encoded")
model = stringIndexer.fit(df)
indexed = model.transform(df)
encoder = OneHotEncoder(dropLast=False, inputCol="workclass_encoded", outputCol="workclass_vec")
encoded = encoder.transform(indexed)
encoded.show(2)
+---+----------+----------------+------+---------+-------------+------------------+---------------+-------------+-----+----+------------+------------+----------+--------------+-----+-----------------+-------------+
|age|age_square|       workclass|fnlwgt|education|education_num|           marital|     occupation| relationship| race| sex|capital_gain|capital_loss|hours_week|native_country|label|workclass_encoded|workclass_vec|
+---+----------+----------------+------+---------+-------------+------------------+---------------+-------------+-----+----+------------+------------+----------+--------------+-----+-----------------+-------------+
| 39|    1521.0|       State-gov| 77516|Bachelors|           13|     Never-married|   Adm-clerical|Not-in-family|White|Male|        2174|           0|        40| United-States|<=50K|              4.0|(9,[4],[1.0])|
| 50|    2500.0|Self-emp-not-inc| 83311|Bachelors|           13|Married-civ-spouse|Exec-managerial|      Husband|White|Male|           0|           0|        13| United-States|<=50K|              1.0|(9,[1],[1.0])|
+---+----------+----------------+------+---------+-------------+------------------+---------------+-------------+-----+----+------------+------------+----------+--------------+-----+-----------------+-------------+
only showing top 2 rows

Construir o pipeline

Vocรช construirรก um pipeline para converter todos os recursos precisos e adicionรก-los ao conjunto de dados final. O pipeline terรก quatro operaรงรตes, mas fique ร  vontade para adicionar quantas operaรงรตes desejar.

  1. Codifique os dados categรณricos
  2. Indexar o recurso de rรณtulo
  3. Adicionar variรกvel contรญnua
  4. Monte as etapas.

Cada etapa รฉ armazenada em uma lista denominada estรกgios. Esta lista informarรก ao VectorAssembler qual operaรงรฃo executar dentro do pipeline.

1. Codifique os dados categรณricos

Esta etapa รฉ exatamente igual ao exemplo acima, exceto que vocรช percorre todos os recursos categรณricos.

from pyspark.ml import Pipeline
from pyspark.ml.feature import OneHotEncoderEstimator
CATE_FEATURES = ['workclass', 'education', 'marital', 'occupation', 'relationship', 'race', 'sex', 'native_country']
stages = [] # stages in our Pipeline
for categoricalCol in CATE_FEATURES:
    stringIndexer = StringIndexer(inputCol=categoricalCol, outputCol=categoricalCol + "Index")
    encoder = OneHotEncoderEstimator(inputCols=[stringIndexer.getOutputCol()],
                                     outputCols=[categoricalCol + "classVec"])
    stages += [stringIndexer, encoder]

Nota sobre a API: O OneHotEncoderEstimator foi reintegrado ao OneHotEncoder em Spark 3.0. Em Spark Na versรฃo 3.x ou posterior, importe OneHotEncoder e passe os mesmos argumentos inputCols e outputCols; o restante do loop permanece inalterado.

2. Indexe o recurso de rรณtulo

Spark, como muitas outras bibliotecas, nรฃo aceita valores de string para o rรณtulo. Vocรช converte o recurso de rรณtulo com StringIndexer e o adiciona aos estรกgios da lista

# Convert label into label indices using the StringIndexer
label_stringIdx =  StringIndexer(inputCol="label", outputCol="newlabel")
stages += [label_stringIdx]

3. Adicione variรกvel contรญnua

O parรขmetro `inputCols` do `VectorAssembler` รฉ uma lista de colunas. Vocรช pode criar uma nova lista contendo todas as novas colunas. O cรณdigo abaixo preenche a lista com as variรกveis โ€‹โ€‹categรณricas codificadas e as variรกveis โ€‹โ€‹contรญnuas.

assemblerInputs = [c + "classVec" for c in CATE_FEATURES] + CONTI_FEATURES

4. Monte as etapas.

Finalmente, vocรช passa todas as etapas no VectorAssembler

assembler = VectorAssembler(inputCols=assemblerInputs, outputCol="features")stages += [assembler]

Agora que todas as etapas estรฃo prontas, vocรช envia os dados para o pipeline.

# Create a Pipeline.
pipeline = Pipeline(stages=stages)
pipelineModel = pipeline.fit(df_remove)
model = pipelineModel.transform(df_remove)

Se vocรช verificar o novo conjunto de dados, verรก que ele contรฉm todos os recursos, transformados e nรฃo transformados. Vocรช estรก interessado apenas no novo rรณtulo e nos recursos. Os recursos incluem todos os recursos transformados e as variรกveis โ€‹โ€‹contรญnuas.

model.take(1)

[Row(age=39, age_square=1521.0, workclass='State-gov', fnlwgt=77516, education='Bachelors', education_num=13, marital='Never-married', occupation='Adm-clerical', relationship='Not-in-family', race='White', sex='Male', capital_gain=2174, capital_loss=0, hours_week=40, native_country='United-States', label='<=50K', workclassIndex=4.0, workclassclassVec=SparseVector(8, {4: 1.0}), educationIndex=2.0, educationclassVec=SparseVector(15, {2: 1.0}), maritalIndex=1.0, maritalclassVec=SparseVector(6, {1: 1.0}), occupationIndex=3.0, occupationclassVec=SparseVector(14, {3: 1.0}), relationshipIndex=1.0, relationshipclassVec=SparseVector(5, {1: 1.0}), raceIndex=0.0, raceclassVec=SparseVector(4, {0: 1.0}), sexIndex=0.0, sexclassVec=SparseVector(1, {0: 1.0}), native_countryIndex=0.0, native_countryclassVec=SparseVector(40, {0: 1.0}), newlabel=0.0, features=SparseVector(99, {4: 1.0, 10: 1.0, 24: 1.0, 32: 1.0, 44: 1.0, 48: 1.0, 52: 1.0, 53: 1.0, 93: 39.0, 94: 77516.0, 95: 2174.0, 96: 13.0, 98: 40.0}))]

Etapa 4) Construa o classificador: logรญstico

Para tornar o cรกlculo mais rรกpido, vocรช converte o modelo em um DataFrame.

Vocรช precisa selecionar um novo rรณtulo e recursos do modelo usando o mapa.

from pyspark.ml.linalg import DenseVector
input_data = model.rdd.map(lambda x: (x["newlabel"], DenseVector(x["features"])))

Vocรช estรก pronto para criar os dados do trem como um DataFrame. Vocรช usa o sqlContext

df_train = sqlContext.createDataFrame(input_data, ["label", "features"])

Verifique a segunda linha

df_train.show(2)
+-----+--------------------+
|label|            features|
+-----+--------------------+
|  0.0|[0.0,0.0,0.0,0.0,...|
|  0.0|[0.0,1.0,0.0,0.0,...|
+-----+--------------------+
only showing top 2 rows

Crie um conjunto de treinamento/teste

Vocรช divide o conjunto de dados 80/20 com randomSplit.

# Split the data into train and test sets
train_data, test_data = df_train.randomSplit([.8,.2],seed=1234)

Vamos contar quantas pessoas com renda abaixo/acima de 50 mil tanto no conjunto de treinamento quanto no conjunto de teste

train_data.groupby('label').agg({'label': 'count'}).show()
+-----+------------+
|label|count(label)|
+-----+------------+
|  0.0|       19698|
|  1.0|        6263|
+-----+------------+
test_data.groupby('label').agg({'label': 'count'}).show()
+-----+------------+
|label|count(label)|
+-----+------------+
|  0.0|        5021|
|  1.0|        1578|
+-----+------------+

Construa o regressor logรญstico

Por รบltimo, mas nรฃo menos importante, vocรช pode construir o classificador.pySpark Possui uma API chamada LogisticRegression para realizar regressรฃo logรญstica.

Vocรช inicializa lr indicando a coluna de rรณtulo e as colunas de recursos. Vocรช define um mรกximo de 10 iteraรงรตes e adiciona um parรขmetro de regularizaรงรฃo com valor 0.3. Observe que na prรณxima seรงรฃo, vocรช usarรก a validaรงรฃo cruzada com uma grade de parรขmetros para ajustar o modelo

# Import `LinearRegression`
from pyspark.ml.classification import LogisticRegression

# Initialize `lr`
lr = LogisticRegression(labelCol="label",
                        featuresCol="features",
                        maxIter=10,
                        regParam=0.3)

# Fit the data to the model
linearModel = lr.fit(train_data)

#Vocรช pode ver os coeficientes da regressรฃo

# Print the coefficients and intercept for logistic regression
print("Coefficients: " + str(linearModel.coefficients))
print("Intercept: " + str(linearModel.intercept))
Coefficients: [-0.0678914665262,-0.153425526813,-0.0706009536407,-0.164057586562,-0.120655298528,0.162922330862,0.149176870438,-0.626836362611,-0.193483661541,-0.0782269980838,0.222667203836,0.399571096381,-0.0222024341804,-0.311925857859,-0.0434497788688,-0.306007744328,-0.41318209688,0.547937504247,-0.395837350854,-0.23166535958,0.618743906733,-0.344088614546,-0.385266881369,0.317324463006,-0.350518889186,-0.201335923138,-0.232878560088,-0.13349278865,-0.119760542498,0.17500602491,-0.0480968101118,0.288484253943,-0.116314616745,0.0524163478063,-0.300952624551,-0.22046421474,-0.16557996579,-0.114676231939,-0.311966431453,-0.344226119233,0.105530129507,0.152243047814,-0.292774545497,0.263628334433,-0.199951374076,-0.30329422583,-0.231087515178,0.418918551,-0.0565930184279,-0.177818073048,-0.0733236680663,-0.267972912252,0.168491215697,-0.12181255723,-0.385648075442,-0.202101794517,0.0469791640782,-0.00842850210625,-0.00373211448629,-0.259296141281,-0.309896554133,-0.168434409756,-0.11048086026,0.0280647963877,-0.204187030092,-0.414392623536,-0.252806580669,0.143366465705,-0.516359222663,-0.435627370849,-0.301949286524,0.0878249035894,-0.210951740965,-0.621417928742,-0.099445190784,-0.232671473401,-0.1077745606,-0.360429419703,-0.420362959052,-0.379729467809,-0.395186242741,0.0826401853838,-0.280251589972,0.187313505214,-0.20295228799,-0.431177064626,0.149759018379,-0.107114299614,-0.319314858424,0.0028450133235,-0.651220387649,-0.327918792207,-0.143659581445,0.00691075160413,8.38517628783e-08,2.18856717378e-05,0.0266701216268,0.000231075966823,0.00893832698698]
Intercept: -1.9884177974805692

Etapa 5) Treine e avalie o modelo

Para gerar previsรฃo para seu conjunto de testes,

Vocรช pode usar linearModel com transform() em test_data

# Make predictions on test data using the transform() method.
predictions = linearModel.transform(test_data)

Vocรช pode imprimir os elementos nas previsรตes

predictions.printSchema()
root
 |-- label: double (nullable = true)
 |-- features: vector (nullable = true)
 |-- rawPrediction: vector (nullable = true)
 |-- probability: vector (nullable = true)
 |-- prediction: double (nullable = false)

Vocรช estรก interessado no rรณtulo, na previsรฃo e na probabilidade

selected = predictions.select("label", "prediction", "probability")
selected.show(20)
+-----+----------+--------------------+
|label|prediction|         probability|
+-----+----------+--------------------+
|  0.0|       0.0|[0.91560704124179...|
|  0.0|       0.0|[0.92812140213994...|
|  0.0|       0.0|[0.92161406774159...|
|  0.0|       0.0|[0.96222760777142...|
|  0.0|       0.0|[0.66363283056957...|
|  0.0|       0.0|[0.65571324475477...|
|  0.0|       0.0|[0.73053376932829...|
|  0.0|       1.0|[0.31265053873570...|
|  0.0|       0.0|[0.80005907577390...|
|  0.0|       0.0|[0.76482251301640...|
|  0.0|       0.0|[0.84447301189069...|
|  0.0|       0.0|[0.75691912026619...|
|  0.0|       0.0|[0.60902504096722...|
|  0.0|       0.0|[0.80799228385509...|
|  0.0|       0.0|[0.87704364852567...|
|  0.0|       0.0|[0.83817652582377...|
|  0.0|       0.0|[0.79655423248500...|
|  0.0|       0.0|[0.82712311232246...|
|  0.0|       0.0|[0.81372823882016...|
|  0.0|       0.0|[0.59687710752201...|
+-----+----------+--------------------+
only showing top 20 rows

Avalie o modelo

Vocรช precisa observar a mรฉtrica de precisรฃo para ver o desempenho (ou ruim) do modelo. Atualmente, nรฃo hรก API para calcular a medida de precisรฃo em Spark. O valor padrรฃo รฉ o ROC, curva caracterรญstica de operaรงรฃo do receptor. ร‰ uma mรฉtrica diferente que leva em consideraรงรฃo a taxa de falsos positivos.

Antes de olhar para o ROC, vamos construir a medida de precisรฃo. Vocรช estรก mais familiarizado com essa mรฉtrica. A medida de precisรฃo รฉ a soma da previsรฃo correta sobre o nรบmero total de observaรงรตes.

Vocรช cria um DataFrame com o rรณtulo e a `prediรงรฃo.

cm = predictions.select("label", "prediction")

Vocรช pode verificar o nรบmero da turma no rรณtulo e na previsรฃo

cm.groupby('label').agg({'label': 'count'}).show()
+-----+------------+
|label|count(label)|
+-----+------------+
|  0.0|        5021|
|  1.0|        1578|
+-----+------------+
cm.groupby('prediction').agg({'prediction': 'count'}).show()
+----------+-----------------+
|prediction|count(prediction)|
+----------+-----------------+
|       0.0|             5982|
|       1.0|              617|
+----------+-----------------+

Por exemplo, no conjunto de teste, hรก 1578 famรญlias com renda acima de 50 mil e 5021 abaixo. O classificador, no entanto, previu 617 famรญlias com rendimentos acima de 50 mil.

Vocรช pode calcular a precisรฃo calculando a contagem quando os rรณtulos sรฃo classificados corretamente no nรบmero total de linhas.

cm.filter(cm.label == cm.prediction).count() / cm.count()

0.8237611759357478

Vocรช pode agrupar tudo e escrever uma funรงรฃo para calcular a precisรฃo.

def accuracy_m(model): 
    predictions = model.transform(test_data)
    cm = predictions.select("label", "prediction")
    acc = cm.filter(cm.label == cm.prediction).count() / cm.count()
    print("Model accuracy: %.3f%%" % (acc * 100)) 
accuracy_m(model = linearModel)
Model accuracy: 82.376%

Mรฉtricas ROC

O mรณdulo BinaryClassificationEvaluator inclui as medidas ROC. O receptor OperaA curva caracterรญstica รฉ outra ferramenta comum usada com classificaรงรฃo binรกria. ร‰ muito semelhante ร  curva de precisรฃo/recall, mas em vez de representar graficamente precisรฃo versus recall, a curva ROC mostra a taxa de verdadeiros positivos (ou seja, recall) contra a taxa de falsos positivos. A taxa de falsos positivos รฉ a proporรงรฃo de instรขncias negativas que sรฃo classificadas incorretamente como positivas. ร‰ igual a um menos a taxa verdadeiramente negativa. A verdadeira taxa negativa tambรฉm รฉ chamada de especificidade. Portanto, a curva ROC representa a sensibilidade (recall) versus 1 โ€“ especificidade

### Use ROC 
from pyspark.ml.evaluation import BinaryClassificationEvaluator

# Evaluate model
evaluator = BinaryClassificationEvaluator(rawPredictionCol="rawPrediction")
print(evaluator.evaluate(predictions))
print(evaluator.getMetricName())

0.8940481662695192รกreaSobROC

print(evaluator.evaluate(predictions))

0.8940481662695192

Etapa 6) Ajustar o hiperparรขmetro

Por รบltimo, mas nรฃo menos importante, vocรช pode ajustar os hiperparรขmetros. De forma semelhante ao scikit-learn, vocรช cria uma grade de parรขmetros e adiciona os parรขmetros que deseja ajustar.

Para reduzir o tempo de cรกlculo, vocรช ajusta apenas o parรขmetro de regularizaรงรฃo com apenas dois valores.

from pyspark.ml.tuning import ParamGridBuilder, CrossValidator

# Create ParamGrid for Cross Validation
paramGrid = (ParamGridBuilder()
             .addGrid(lr.regParam, [0.01, 0.5])
             .build())

Por fim, vocรช avalia o modelo usando o mรฉtodo de validaรงรฃo cruzada com 5 folds. O treinamento leva cerca de 16 minutos.

from time import *
start_time = time()

# Create 5-fold CrossValidator
cv = CrossValidator(estimator=lr,
                    estimatorParamMaps=paramGrid,
                    evaluator=evaluator, numFolds=5)

# Run cross validations
cvModel = cv.fit(train_data)
# likely take a fair amount of time
end_time = time()
elapsed_time = end_time - start_time
print("Time to train model: %.3f seconds" % elapsed_time)

Tempo para treinar o modelo: 978.807 segundos

O melhor hiperparรขmetro de regularizaรงรฃo รฉ 0.01, com precisรฃo de 85.316 por cento.

accuracy_m(model = cvModel)
Model accuracy: 85.316%

Vocรช pode extract o parรขmetro recomendado encadeando cvModel.bestModel com extractParamMap()

bestModel = cvModel.bestModel
bestModel.extractParamMap()
{Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='aggregationDepth', doc='suggested depth for treeAggregate (>= 2)'): 2,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='elasticNetParam', doc='the ElasticNet mixing parameter, in range [0, 1]. For alpha = 0, the penalty is an L2 penalty. For alpha = 1, it is an L1 penalty'): 0.0,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='family', doc='The name of family which is a description of the label distribution to be used in the model. Supported options: auto, binomial, multinomial.'): 'auto',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='featuresCol', doc='features column name'): 'features',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='fitIntercept', doc='whether to fit an intercept term'): True,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='labelCol', doc='label column name'): 'label',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='maxIter', doc='maximum number of iterations (>= 0)'): 10,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='predictionCol', doc='prediction column name'): 'prediction',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='probabilityCol', doc='Column name for predicted class conditional probabilities. Note: Not all models output well-calibrated probability estimates! These probabilities should be treated as confidences, not precise probabilities'): 'probability',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='rawPredictionCol', doc='raw prediction (a.k.a. confidence) column name'): 'rawPrediction',
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='regParam', doc='regularization parameter (>= 0)'): 0.01,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='standardization', doc='whether to standardize the training features before fitting the model'): True,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='threshold', doc='threshold in binary classification prediction, in range [0, 1]'): 0.5,
 Param(parent='LogisticRegression_4d8f8ce4d6a02d8c29a0', name='tol', doc='the convergence tolerance for iterative algorithms (>= 0)'): 1e-06}

Perguntas Frequentes

Um RDD รฉ uma coleรงรฃo distribuรญda sem tipos que vocรช transforma com map e filter. Um DataFrame adiciona um esquema nomeado e passa pelo otimizador Catalyst, portanto, geralmente รฉ mais rรกpido e fรกcil de consultar para dados estruturados.

Spark 2.x necessรกrio Java 8 apenas. Spark As versรตes 3.x e 4.x funcionam em Java 8, 11 e 17, e suporte Python 3.8 ou superior. Sempre certifique-se de que o JDK seja compatรญvel com o Spark lanรงamento, porque uma versรฃo mais recente do JDK quebra versรตes mais antigas.

Assistentes de IA leem Spark As mรฉtricas da interface do usuรกrio e os planos de execuรงรฃo sinalizam partiรงรตes desbalanceadas, grandes embaralhamentos e excesso de memรณria, sugerindo entรฃo o reparticionamento ou junรงรตes de broadcast. Isso reduz o trabalho de ajuste que antes exigia a inspeรงรฃo manual de cada etapa de execuรงรฃo.

O Copilot gera cรณdigo boilerplate de forma eficiente: conversรตes de tipo com `withColumn`, agregaรงรตes com `groupBy` e estรกgios de pipeline. Os nomes das colunas e as chaves de junรงรฃo ainda precisam ser verificados em relaรงรฃo ao esquema real, pois o cรณdigo gerado compila sem problemas, embora selecione silenciosamente o campo errado.

Escolha o pandas enquanto os dados couberem confortavelmente na memรณria de uma รบnica mรกquina. Migre para o Python.Spark Quando os arquivos excedem a RAM disponรญvel, quando o trabalho precisa ser executado em um cluster ou quando a mesma tarefa alimenta um pipeline de produรงรฃo em vez de um notebook exploratรณrio.

Py4JJavaO erro expรตe uma exceรงรฃo da JVM atravรฉs do Python ponte. Os gatilhos comuns sรฃo um JDK ausente ou incompatรญvel, um JAVA_HOME nรฃo definido ou um PySpark versรฃo construรญda contra uma diferenรงa Spark liberar mais do que aquele no caminho.

Salve o script como um arquivo .py e execute-o com spark-submit, adicionando --master para escolher o modo local ou cluster. O mesmo cรณdigo que รฉ executado dentro Jupyter funciona sem alteraรงรตes uma vez SparkA sessรฃo รฉ criada explicitamente.

Transformaรงรตes como map, filter e withColumn apenas criam um plano. Nada รฉ executado atรฉ que uma aรงรฃo como count, collect ou show seja realizada. Spark Em seguida, otimiza toda a cadeia de uma sรณ vez, evitando a escrita de resultados intermediรกrios desnecessรกrios.

Resuma esta postagem com: