PySpark Tutorial pentru începători: Învață cu EXEMPLE

Înainte de a învăța PySpark, hai sa intelegem:

Ce este Apache Spark?

Spark este o soluție de date mari care s-a dovedit a fi mai ușoară și mai rapidă decât Hadoop MapReduce. Spark este un software open source dezvoltat de laboratorul UC Berkeley RAD în 2009. De când a fost lansat publicului în 2010, Spark a crescut în popularitate și este folosit în industrie cu o scară fără precedent.

În epoca din Datele mari, practicienii au nevoie mai mult ca oricând de instrumente rapide și fiabile pentru a procesa fluxul de date. Instrumentele anterioare precum MapReduce erau preferate, dar erau lente. Pentru a depăși această problemă, Spark oferă o soluție rapidă și de uz general. Principala diferență între Spark și MapReduce este asta Spark rulează calcule în memorie în timpul ulterioară pe hard disk. Permite accesul de mare viteză și procesarea datelor, reducând timpul de la ore la minute.

Ce este PySpark?

PySpark este un instrument creat de Apache Spark Comunitate pentru utilizare Python implementate cu Spark. Permite lucrul cu RDD (Resilient Distributed Dataset) în Python. De asemenea, oferă PySpark Shell pentru a lega Python API-uri cu Spark miez pentru a iniția Spark Context. Spark este motorul de nume pentru a realiza cluster-computing, în timp ce PySpark is Pythonbiblioteca lui de utilizat Spark.

Cum se Spark funcționează?

Spark se bazează pe un motor de calcul, adică se ocupă de aplicația de programare, distribuire și monitorizare. Fiecare sarcină este realizată pe diferite mașini de lucru numite cluster de calcul. Un cluster de calcul se referă la împărțirea sarcinilor. O mașină îndeplinește o sarcină, în timp ce celelalte contribuie la rezultatul final printr-o sarcină diferită. În cele din urmă, toate sarcinile sunt agregate pentru a produce o ieșire. The Spark admin oferă o imagine de ansamblu 360 a diverselor Spark Locuri de munca.

Cum Spark Apartamente
Cum Spark Apartamente

Spark este proiectat pentru a lucra cu

  • Python
  • Java
  • Scala
  • SQL

O caracteristică semnificativă a Spark este cantitatea mare de bibliotecă încorporată, inclusiv MLlib pentru învățarea automată. Spark este, de asemenea, proiectat să funcționeze cu clustere Hadoop și poate citi tipul larg de fișiere, inclusiv date Hive, CSV, JSON, date Casandra, printre altele.

De ce sa folosim Spark?

În calitate de viitor practicant de date, ar trebui să fiți familiarizat cu bibliotecile celebre ale lui Python: Pandas și scikit-learn. Aceste două biblioteci sunt fantastice pentru a explora seturi de date până la dimensiuni medii. Proiectele obișnuite de învățare automată sunt construite în jurul următoarei metodologii:

  • Încărcați datele pe disc
  • Importați datele în memoria aparatului
  • Prelucrează/analizează datele
  • Construiți modelul de învățare automată
  • Stocați predicția înapoi pe disc

Problema apare dacă cercetătorul dorește să proceseze date prea mari pentru un singur computer. În zilele anterioare ale științei datelor, practicienii le-au eșantionat, deoarece instruirea pe seturi uriașe de date nu era întotdeauna necesară. Oamenii de știință de date ar găsi un eșantion statistic bun, ar efectua o verificare suplimentară a robusteței și va veni cu un model excelent.

Cu toate acestea, există câteva probleme cu aceasta:

  • Setul de date reflectă lumea reală?
  • Datele includ un exemplu specific?
  • Este modelul potrivit pentru eșantionare?

Luați recomandarea utilizatorilor, de exemplu. Recomandatorii se bazează pe compararea utilizatorilor cu alți utilizatori în evaluarea preferințelor acestora. Dacă practicianul de date preia doar un subset de date, nu va exista o cohortă de utilizatori care sunt foarte asemănători unul cu celălalt. Recomandatorii trebuie să ruleze pe setul de date complet sau deloc.

Care este solutia?

Soluția a fost evidentă de mult timp, împărțind problema pe mai multe computere. Calculul paralel vine și cu mai multe probleme. Dezvoltatorii au adesea probleme la scrierea codului paralel și ajung să fie nevoiți să rezolve o mulțime de probleme complexe legate de procesarea multiplă în sine.

Pyspark oferă cercetătorului de date un API care poate fi folosit pentru a rezolva problemele de procedură de date paralele. Pyspark se ocupă de complexitățile multiprocesării, cum ar fi distribuirea datelor, distribuirea codului și colectarea rezultatelor de la lucrători pe un cluster de mașini.

Spark poate rula autonom, dar cel mai adesea rulează pe un cadru de calcul cluster, cum ar fi Hadoop. În timpul testării și dezvoltării, totuși, un cercetător de date poate rula eficient Spark pe casetele lor de dezvoltare sau laptopurile fără cluster

• Unul dintre principalele avantaje ale Spark este de a construi o arhitectură care să cuprindă gestionarea fluxului de date, interogări de date fără întreruperi, predicție de învățare automată și acces în timp real la diverse analize.

• Spark lucrează îndeaproape cu limbajul SQL, adică cu datele structurate. Permite interogarea datelor în timp real.

• Sarcina principală a cercetătorului de date este să analizeze și să construiască modele predictive. Pe scurt, un cercetător de date trebuie să știe cum să interogheze datele folosind SQL, produceți un raport statistic și utilizați învățarea automată pentru a produce predicții. Oamenii de știință de date își petrec o cantitate semnificativă din timpul lor curățării, transformării și analizării datelor. Odată ce setul de date sau fluxul de lucru de date este gata, cercetătorul de date utilizează diverse tehnici pentru a descoperi perspective și modele ascunse. Manipularea datelor ar trebui să fie robustă și la fel de ușor de utilizat. Spark este instrumentul potrivit datorită vitezei și API-urilor bogate.

În acest PySpark tutorial, veți învăța cum să construiți un clasificator cu PySpark exemple.

Cum se instalează PySpark cu AWS

Jupyter echipa a construi o imagine Docker pentru a rula Spark eficient. Mai jos sunt pașii pe care îi puteți urma pentru a instala PySpark exemplu în AWS.

Consultați tutorialul nostru pe AWS și TensorFlow

Pasul 1: Creați o instanță

În primul rând, trebuie să creați o instanță. Accesați contul dvs. AWS și lansați instanța. Puteți crește spațiul de stocare până la 15 g și puteți utiliza același grup de securitate ca în tutorialul TensorFlow.

Pasul 2: deschideți conexiunea

Deschideți conexiunea și instalați containerul docker. Pentru mai multe detalii, consultați tutorialul cu TensorFlow cu Docher. Rețineți că, trebuie să vă aflați în directorul de lucru corect.

Pur și simplu rulați aceste coduri pentru a instala Docker:

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

Pasul 3: Redeschideți conexiunea și instalați Spark

După ce redeschideți conexiunea, puteți instala imaginea care conține 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

Pasul 4: Deschideți Jupyter

Verificați recipientul și numele acestuia

docker ps

Lansați docker-ul cu jurnalele docker urmate de numele docker-ului. De exemplu, docker înregistrează zealous_goldwasser

Accesați browserul și lansați Jupyter. Adresa este http://localhost:8888/. Lipiți parola dată de terminal.

notițe: dacă doriți să încărcați/descărcați un fișier pe computerul dvs. AWS, puteți utiliza software-ul Cyberduck, https://cyberduck.io/.

Cum se instalează PySpark on Windows/Mac cu Conda

Mai jos este un proces detaliat despre cum să instalați PySpark on Windows/Mac folosind Anaconda:

Pentru a instala Spark pe mașina dvs. locală, o practică recomandată este să creați un nou mediu conda. Acest nou mediu se va instala Python 3.6, Spark și toate dependențele.

Utilizator Mac

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

Windows Utilizator

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

Puteți edita fișierul .yml. Fiți precaut cu indentarea. Sunt necesare două spații înainte -

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

Salvează-l și creează mediul. Este nevoie de ceva timp

conda env create -f hello-spark.yml

Pentru mai multe detalii despre locație, consultați tutorialul Instalați TensorFlow

Puteți verifica tot mediul instalat în mașina dvs

conda env list
Activate hello-spark

Utilizator Mac

source activate hello-spark

Windows Utilizator

activate hello-spark

Notă: Ați creat deja un mediu specific TensorFlow pentru a rula tutorialele pe TensorFlow. Este mai convenabil să creați un nou mediu diferit de hello-tf. Nu are sens să supraîncărcați cu hello-tf Spark sau orice alte biblioteci de învățare automată.

Imaginează-ți că cea mai mare parte a proiectului tău implică TensorFlow, dar trebuie să-l folosești Spark pentru un anumit proiect. Puteți seta un mediu TensorFlow pentru tot proiectul dvs. și puteți crea un mediu separat pentru Spark. Puteți adăuga cât mai multe biblioteci în Spark mediul dorit, fără a interfera cu mediul TensorFlow. Odată ce ați terminat cu Sparkproiectul lui, îl puteți șterge fără a afecta mediul TensorFlow.

Jupyter

Operatii Deschise Jupyter Notebook și încercați dacă PySpark fabrică. Într-un caiet nou lipiți următorul PySpark cod simplu:

import pyspark
from pyspark import SparkContext
sc =SparkContext()

Dacă apare o eroare, este posibil ca Java nu este instalat pe mașina dvs. În mac, deschideți terminalul și scrieți java -version, dacă există o versiune java, asigurați-vă că este 1.8. În Windows, accesați Aplicație și verificați dacă există o Java pliant. Dacă există o Java folder, verifică asta Java 1.8 este instalat. În momentul în care scriem acest lucru, PySpark nu este compatibil cu Java9 și mai sus.

Dacă trebuie să instalați Java, să te gândești legătură și descărcați jdk-8u181-windows-x64.exe

Jupyter

Pentru utilizatorii Mac, se recomandă utilizarea „brew.”.

brew tap caskroom/versions
brew cask install java8

Consultați acest tutorial pas cu pas cum să instalați Java

notițe: Utilizați Eliminare pentru a șterge complet un mediu.

 conda env remove -n hello-spark -y

Spark Context

SparkContextul este motorul intern care permite conexiunile cu clusterele. Dacă doriți să efectuați o operațiune, aveți nevoie de un SparkContext.

Crearea unei SparkContext

În primul rând, trebuie să inițiezi a SparkContext.

import pyspark
from pyspark import SparkContext
sc =SparkContext()

Acum, că SparkContextul este gata, puteți crea o colecție de date numită RDD, Resilient Distributed Dataset. Calculul într-un RDD este paralelizat automat în cluster.

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

Puteți accesa primul rând cu take

nums.take(1)
[1]

Puteți aplica o transformare datelor cu o funcție lambda. În PySpark exemplu de mai jos, returnați pătratul numerelor. Este o transformare a hărții

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

SQLContext

O modalitate mai convenabilă este utilizarea DataFrame. SparkContextul este deja setat, îl puteți folosi pentru a crea dataFrame. De asemenea, trebuie să declarați SQLContext

SQLContext permite conectarea motorului cu diferite surse de date. Este folosit pentru a iniția funcționalitățile de Spark sql.

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

sqlContext = SQLContext(sc)

Acum în asta Spark tutorial Python, să creăm o listă de tuplu. Fiecare tuplu va conține numele oamenilor și vârsta acestora. Sunt necesari patru pași:

Pas 1) Creați lista de tuplu cu informații

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

Pas 2) Construiește un RDD

rdd = sc.parallelize(list_p)

Pas 3) Convertiți tuplurile

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

Pas 4) Creați un context 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)

Dacă doriți să accesați tipul fiecărei caracteristici, puteți utiliza printSchema()

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

Exemplu de învățare automată cu PySpark

Acum că ai o scurtă idee despre Spark și SQLContext, sunteți gata să vă construiți primul program de învățare automată.

Următorii sunt pașii pentru a construi un program de învățare automată cu PySpark:

  • Pas 1) Operațiune de bază cu PySpark
  • Pas 2) Preprocesare de date
  • Pas 3) Construiți o conductă de procesare a datelor
  • Pas 4) Construiți clasificatorul: logistic
  • Pas 5) Antrenează și evaluează modelul
  • Pas 6) Reglați hiperparametrul

În acest PySpark Tutorial de învățare automată, vom folosi setul de date pentru adulți. Scopul acestui tutorial este să înveți cum să folosești Pyspark. Pentru mai multe informații despre setul de date, consultați acest tutorial.

Rețineți că setul de date nu este semnificativ și puteți crede că calculul durează mult. Spark este conceput pentru a procesa o cantitate considerabilă de date. SparkPerformanțele lui cresc în comparație cu alte biblioteci de învățare automată atunci când setul de date procesat crește.

Pasul 1) Operare de bază cu PySpark

În primul rând, trebuie să inițializați SQLContextul care nu este deja inițiat încă.

#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)

apoi, puteți citi fișierul cvs cu sqlContext.read.csv. Folosiți inferSchema setat la True pentru a spune Spark pentru a ghici automat tipul de date. În mod implicit, este pornirea la Fals.

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

Să aruncăm o privire la tipul de date

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)

Puteți vedea datele cu 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

Dacă nu ați setat inderShema la True, iată ce se întâmplă cu tipul. Sunt toate în șir.

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)

Pentru a converti variabila continuă în formatul corect, puteți utiliza reformularea coloanelor. Puteți folosi withColumn pentru a spune Spark ce coloană să opereze transformarea.

# 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()

Selectați coloane

Puteți selecta și afișa rândurile cu select și numele caracteristicilor. Mai jos sunt selectate vârsta și fnlwgt.

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

Numărați pe grupe

Dacă doriți să numărați numărul de apariții în funcție de grup, puteți înlănțui:

  • a se grupa cu()
  • numara()

împreună. În PySpark exemplu de mai jos, numărați numărul de rânduri după nivelul de educație.

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|
+------------+-----+

Descrieți datele

Pentru a obține o statistică rezumată a datelor, puteți utiliza describe(). Acesta va calcula:

  • conta
  • însemna
  • deviație standard
  • minute
  • 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|
+-------+------------------+-----------+------------------+------------+-----------------+--------+----------------+------------+------------------+------+------------------+----------------+------------------+--------------+-----+

Dacă doriți rezumatul statisticii pentru o singură coloană, adăugați numele coloanei în interiorul describe()

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

calcul crosstab

În unele ocazii, poate fi interesant să vezi statisticile descriptive între două coloane pe perechi. De exemplu, puteți număra numărul de persoane cu venituri sub sau peste 50k în funcție de nivelul de educație. Această operație se numește tablă încrucișată.

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

Puteți vedea că nimeni nu are venituri mai mari de 50 când sunt tineri.

Aruncați coloana

Există două API intuitive pentru a arunca coloane:

  • drop(): Aruncă o coloană
  • dropna(): Aruncă NA

Mai jos plasați coloana 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']

Filtrați datele

Puteți utiliza filter() pentru a aplica statistici descriptive într-un subset de date. De exemplu, puteți număra numărul de persoane cu vârsta peste 40 de ani

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

13443

Descriptstatistici pe grupe

În cele din urmă, puteți grupa datele după grup și puteți calcula operațiuni statistice precum media.

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|
+--------------------+------------------+

Pasul 2) Preprocesarea datelor

Procesarea datelor este un pas critic în învățarea automată. După ce eliminați datele de gunoi, obțineți câteva informații importante.

De exemplu, știți că vârsta nu este o funcție liniară cu venitul. Când oamenii sunt tineri, veniturile lor sunt de obicei mai mici decât vârsta mijlocie. După pensionare, o gospodărie își folosește economiile, adică o scădere a venitului. Pentru a captura acest model, puteți adăuga un pătrat la caracteristica de vârstă

Adăugați pătratul de vârstă

Pentru a adăuga o funcție nouă, trebuie să:

  1. Selectați coloana
  2. Aplicați transformarea și adăugați-o la 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)

Puteți vedea că age_square a fost adăugat cu succes la cadrul de date. Puteți modifica ordinea variabilelor cu select. Mai jos, aduci age_square imediat după vârstă.

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')

Excludeți Olanda-Țările de Jos

Când un grup dintr-o caracteristică are o singură observație, nu aduce nicio informație modelului. Dimpotrivă, poate duce la o eroare în timpul validării încrucișate.

Să verificăm originea gospodăriei

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

Caracteristica native_country are o singură gospodărie care provine din Olanda. Îl excluzi.

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

Pasul 3) Construiți o conductă de procesare a datelor

Similar cu scikit-learn, Pyspark are un API pipeline.

O conductă este foarte convenabilă pentru a menține structura datelor. Împingeți datele în conductă. În interiorul conductei se efectuează diverse operații, ieșirea este folosită pentru a alimenta algoritmul.

De exemplu, o transformare universală în învățarea automată constă în conversia unui șir într-un codificator fierbinte, adică o coloană de către un grup. Un codificator fierbinte este de obicei o matrice plină de zerouri.

Pașii de transformare a datelor sunt foarte similari cu scikit-learn. Trebuie să:

  • Indexați șirul la numeric
  • Creați un codificator fierbinte
  • Transformă datele

Două API-uri fac treaba: StringIndexer, OneHotEncoder

  1. În primul rând, selectați coloana șir de indexat. inputCol este numele coloanei din setul de date. outputCol este noul nume dat coloanei transformate.
StringIndexer(inputCol="workclass", outputCol="workclass_encoded")
  1. Potriviți datele și transformați-le
model = stringIndexer.fit(df)		
`indexed = model.transform(df)``
  1. Creați coloanele de știri în funcție de grup. De exemplu, dacă există 10 grupuri în caracteristică, noua matrice va avea 10 coloane, câte una pentru fiecare grup.
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

Construiți conducta

Veți construi o conductă pentru a converti toate caracteristicile precise și a le adăuga la setul de date final. Conducta va avea patru operațiuni, dar nu ezitați să adăugați câte operațiuni doriți.

  1. Codificați datele categoriale
  2. Indexați caracteristica etichetei
  3. Adăugați o variabilă continuă
  4. Asamblați treptele.

Fiecare pas este stocat într-o listă numită etape. Această listă îi va spune VectorAssembler-ului ce operație să efectueze în interiorul conductei.

1. Codificați datele categoriale

Acest pas este exact același cu exemplul de mai sus, cu excepția faptului că treceți peste toate caracteristicile categoriale.

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]

2. Indexați caracteristica etichetei

Spark, ca multe alte biblioteci, nu acceptă valori de șir pentru etichetă. Convertiți caracteristica de etichetă cu StringIndexer și o adăugați la etapele listei

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

3. Adăugați o variabilă continuă

inputCols ale VectorAssembler este o listă de coloane. Puteți crea o nouă listă care să conțină toate coloanele noi. Codul de mai jos completează lista cu caracteristici categorice codificate și caracteristici continue.

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

4. Asamblați treptele.

În cele din urmă, treci toți pașii din VectorAssembler

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

Acum că toți pașii sunt gata, împingeți datele în conductă.

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

Dacă verificați noul set de date, puteți vedea că acesta conține toate caracteristicile, transformate și nu. Te interesează doar noua etichetă și funcții. Caracteristicile includ toate caracteristicile transformate și variabilele continue.

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}))]

Pasul 4) Construiți clasificatorul: logistic

Pentru a face calculul mai rapid, convertiți modelul într-un DataFrame.

Trebuie să selectați eticheta nouă și caracteristicile din model folosind harta.

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

Sunteți gata să creați datele trenului ca DataFrame. Folosiți sqlContext

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

Verificați al doilea rând

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

Creați un tren/set de testare

Împărțiți setul de date 80/20 cu randomSplit.

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

Să numărăm câte persoane cu venituri sub/peste 50k atât în ​​setul de antrenament, cât și în test

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|
+-----+------------+

Construiți regresorul logistic

Nu în ultimul rând, puteți construi clasificatorul. Pyspark are un API numit LogisticRegression pentru a efectua regresia logistică.

Inițializați lr indicând coloana de etichetă și coloanele de caracteristici. Setați maximum 10 iterații și adăugați un parametru de regularizare cu o valoare de 0.3. Rețineți că în secțiunea următoare, veți folosi validarea încrucișată cu o grilă de parametri pentru a regla modelul

# 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)

#Puteți vedea coeficienții din regresie

# 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

Pasul 5) Antrenează și evaluează modelul

Pentru a genera predicții pentru setul dvs. de testare,

Puteți utiliza linearModel cu transform() pe test_data

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

Puteți imprima elementele în predicții

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

Sunteți interesat de etichetă, predicție și probabilitate

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

Evaluați modelul

Trebuie să te uiți la metrica de precizie pentru a vedea cât de bine (sau de rău) funcționează modelul. În prezent, nu există un API în care să se calculeze măsura de precizie Spark. Valoarea implicită este ROC, curba caracteristică de funcționare a receptorului. Este o măsurătoare diferită care ia în considerare rata fals pozitive.

Înainte de a vă uita la ROC, să construim măsura de precizie. Sunteți mai familiarizat cu această valoare. Măsura preciziei este suma predicției corecte asupra numărului total de observații.

Creați un DataFrame cu eticheta și `predicția.

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

Puteți verifica numărul de clasă din etichetă și predicția

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|
+----------+-----------------+

De exemplu, în setul de testare, există 1578 de gospodării cu un venit peste 50k și 5021 mai jos. Clasificatorul a prezis însă 617 gospodării cu venituri peste 50k.

Puteți calcula acuratețea calculând numărul atunci când etichetele sunt clasificate corect pe numărul total de rânduri.

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

0.8237611759357478

Puteți împacheta totul și scrie o funcție pentru a calcula acuratețea.

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%

Valori ROC

Modulul BinaryClassificationEvaluator include măsurile ROC. Destinatarul OperaCurba caracteristică este un alt instrument comun utilizat cu clasificarea binară. Este foarte asemănătoare cu curba de precizie/rechemare, dar în loc de a reprezenta un grafic precizie în funcție de reamintire, curba ROC arată rata pozitivă adevărată (adică reamintirea) față de rata fals pozitivă. Rata fals pozitive este raportul dintre cazurile negative care sunt clasificate incorect drept pozitive. Este egal cu unu minus rata negativă adevărată. Rata negativă adevărată se mai numește și specificitate. Prin urmare, curba ROC prezintă sensibilitatea (reamintirea) față de 1 – specificitate

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

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

0.8940481662695192zonaSubROC

print(evaluator.evaluate(predictions))

0.8940481662695192

Pasul 6) Reglați hiperparametrul

Nu în ultimul rând, puteți regla hiperparametrii. Similar cu scikit invata creați o grilă de parametri și adăugați parametrii pe care doriți să-i reglați.

Pentru a reduce timpul de calcul, reglați parametrul de regularizare doar cu doar două valori.

from pyspark.ml.tuning import ParamGridBuilder, CrossValidator

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

În cele din urmă, evaluați modelul folosind metoda de validare încrucișată cu 5 ori. Durează aproximativ 16 minute pentru a te antrena.

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)

Timp de antrenament al modelului: 978.807 secunde

Cel mai bun hiperparametru de regularizare este 0.01, cu o precizie de 85.316 la sută.

accuracy_m(model = cvModel)
Model accuracy: 85.316%

Puteți extrage parametrul recomandat prin înlănțuirea cvModel.bestModel cu 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}

Rezumat

Spark este un instrument fundamental pentru un cercetător de date. Acesta permite practicianului să conecteze o aplicație la diferite surse de date, să efectueze analiza datelor fără probleme sau să adauge un model predictiv.

Pentru început Spark, trebuie să inițiezi a Spark Context cu:

"SparkContext()'

si si SQL context pentru a vă conecta la o sursă de date:

„SQLContext()”

În tutorial, înveți cum să antrenezi o regresie logistică:

  1. Convertiți setul de date într-un cadru de date cu:
rdd.map(lambda x: (x["newlabel"], DenseVector(x["features"])))
sqlContext.createDataFrame(input_data, ["label", "features"])

Rețineți că numele coloanei etichetei este newlabel și toate caracteristicile sunt adunate în caracteristici. Modificați aceste valori dacă sunt diferite în setul dvs. de date.

  1. Creați trenul/setul de testare
randomSplit([.8,.2],seed=1234)
  1. Antrenează modelul
LogisticRegression(labelCol="label",featuresCol="features",maxIter=10, regParam=0.3)
lr.fit()
  1. Faceți predicții
linearModel.transform()

Rezumați această postare cu: