Použití knihovny Apache Spark MLlib k vytvoření aplikace strojového učení a analýze datové sady

Naučte se používat Apache Spark MLlib k vytvoření aplikace strojového učení. Aplikace provede prediktivní analýzu otevřené datové sady. Z integrovaných knihoven strojového učení Sparku tento příklad používá klasifikaci prostřednictvím logistické regrese.

Knihovna MLlib je základní knihovna Spark, která poskytuje mnoho nástrojů užitečných pro úlohy strojového učení, například:

  • Klasifikace
  • Regrese
  • Clustering
  • Modelování
  • Rozklad hodnoty s jednotným číslem (SVD) a analýza hlavních komponent (PCA)
  • Testování hypotéz a výpočet vzorové statistiky

Vysvětlení klasifikace a logistické regrese

Klasifikace, oblíbená úloha strojového učení, je proces řazení vstupních dat do kategorií. Je úlohou klasifikačního algoritmu zjistit, jak přiřadit "popisky" vstupním datům, která zadáte. Můžete si například představit algoritmus strojového učení, který přijímá informace o akciích jako vstup. Pak akcie rozdělí do dvou kategorií: akcie, které byste měli prodávat, a akcie, které byste měli zachovat.

Logistická regrese je algoritmus, který používáte pro klasifikaci. Rozhraní API logistické regrese Sparku je užitečné pro binární klasifikaci nebo klasifikaci vstupních dat do jedné ze dvou skupin. Další informace o logistické regresi najdete na Wikipedii.

V souhrnu proces logistické regrese vytváří logistickou funkci. Pomocí funkce můžete předpovědět pravděpodobnost, že vstupní vektor patří do jedné skupiny nebo druhé.

Příklad prediktivní analýzy údajů o kontrole potravin

V tomto příkladu pomocí Sparku provedete prediktivní analýzu údajů o kontrole potravin (Food_Inspections1.csv). Data získaná prostřednictvím datového portálu City of Chicago. Tato datová sada obsahuje informace o kontrolách potravin, které byly provedeny v Chicagu. Včetně informací o každém zařízení, nalezených porušení (pokud existuje) a výsledků kontroly. Datový soubor CSV je již k dispozici v účtu úložiště přidruženém ke clusteru ve složce /HdiSamples/HdiSamples/FoodInspectionData/Food_Inspections1.csv.

V následujících krocích vytvoříte model, abyste zjistili, co je potřeba k předání nebo selhání kontroly potravin.

Vytvoření aplikace strojového učení Apache Spark MLlib

  1. Vytvořte poznámkový blok Jupyter pomocí jádra PySpark. Pokyny najdete v tématu Vytvoření souboru Jupyter Notebook.

  2. Importujte typy požadované pro tuto aplikaci. Zkopírujte a vložte následující kód do prázdné buňky a stiskněte kombinaci kláves SHIFT+ENTER.

    from pyspark.ml import Pipeline
    from pyspark.ml.classification import LogisticRegression
    from pyspark.ml.feature import HashingTF, Tokenizer
    from pyspark.sql import Row
    from pyspark.sql.functions import UserDefinedFunction
    from pyspark.sql.types import *
    

    Kvůli jádru PySpark nemusíte explicitně vytvářet žádné kontexty. Kontexty Spark a Hive se automaticky vytvoří při spuštění první buňky kódu.

Vytvoření vstupního datového rámce

Pomocí kontextu Sparku můžete načíst nezpracovaná data CSV do paměti jako nestrukturovaný text. Pak pomocí knihovny CSV Pythonu parsujte každý řádek dat.

  1. Spuštěním následujících řádků vytvořte odolnou distribuovanou datovou sadu (RDD) importem a parsováním vstupních dat.

    def csvParse(s):
        import csv
        from io import StringIO
        sio = StringIO(s)
        value = next(csv.reader(sio))
        sio.close()
        return value
    
    inspections = sc.textFile('/HdiSamples/HdiSamples/FoodInspectionData/Food_Inspections1.csv')\
                    .map(csvParse)
    
  2. Spuštěním následujícího kódu načtěte jeden řádek ze sady RDD, abyste se mohli podívat na schéma dat:

    inspections.take(1)
    

    Výstup je:

    [['413707',
        'LUNA PARK INC',
        'LUNA PARK  DAY CARE',
        '2049789',
        "Children's Services Facility",
        'Risk 1 (High)',
        '3250 W FOSTER AVE ',
        'CHICAGO',
        'IL',
        '60625',
        '09/21/2010',
        'License-Task Force',
        'Fail',
        '24. DISH WASHING FACILITIES: PROPERLY DESIGNED, CONSTRUCTED, MAINTAINED, INSTALLED, LOCATED AND OPERATED - Comments: All dishwashing machines must be of a type that complies with all requirements of the plumbing section of the Municipal Code of Chicago and Rules and Regulation of the Board of Health. OBSEVERD THE 3 COMPARTMENT SINK BACKING UP INTO THE 1ST AND 2ND COMPARTMENT WITH CLEAR WATER AND SLOWLY DRAINING OUT. INST NEED HAVE IT REPAIR. CITATION ISSUED, SERIOUS VIOLATION 7-38-030 H000062369-10 COURT DATE 10-28-10 TIME 1 P.M. ROOM 107 400 W. SURPERIOR. | 36. LIGHTING: REQUIRED MINIMUM FOOT-CANDLES OF LIGHT PROVIDED, FIXTURES SHIELDED - Comments: Shielding to protect against broken glass falling into food shall be provided for all artificial lighting sources in preparation, service, and display facilities. LIGHT SHIELD ARE MISSING UNDER HOOD OF  COOKING EQUIPMENT AND NEED TO REPLACE LIGHT UNDER UNIT. 4 LIGHTS ARE OUT IN THE REAR CHILDREN AREA,IN THE KINDERGARDEN CLASS ROOM. 2 LIGHT ARE OUT EAST REAR, LIGHT FRONT WEST ROOM. NEED TO REPLACE ALL LIGHT THAT ARE NOT WORKING. | 35. WALLS, CEILINGS, ATTACHED EQUIPMENT CONSTRUCTED PER CODE: GOOD REPAIR, SURFACES CLEAN AND DUST-LESS CLEANING METHODS - Comments: The walls and ceilings shall be in good repair and easily cleaned. MISSING CEILING TILES WITH STAINS IN WEST,EAST, IN FRONT AREA WEST, AND BY THE 15MOS AREA. NEED TO BE REPLACED. | 32. FOOD AND NON-FOOD CONTACT SURFACES PROPERLY DESIGNED, CONSTRUCTED AND MAINTAINED - Comments: All food and non-food contact equipment and utensils shall be smooth, easily cleanable, and durable, and shall be in good repair. SPLASH GUARDED ARE NEEDED BY THE EXPOSED HAND SINK IN THE KITCHEN AREA | 34. FLOORS: CONSTRUCTED PER CODE, CLEANED, GOOD REPAIR, COVING INSTALLED, DUST-LESS CLEANING METHODS USED - Comments: The floors shall be constructed per code, be smooth and easily cleaned, and be kept clean and in good repair. INST NEED TO ELEVATE ALL FOOD ITEMS 6INCH OFF THE FLOOR 6 INCH AWAY FORM WALL.  ',
        '41.97583445690982',
        '-87.7107455232781',
        '(41.97583445690982, -87.7107455232781)']]
    

    Výstup vám poskytne představu o schématu vstupního souboru. Zahrnuje název každé provozovny a typ zařízení. Adresa, údaje o kontrolách a umístění mimo jiné.

  3. Spuštěním následujícího kódu vytvořte datový rámec (df) a dočasnou tabulku (CountResults) s několika sloupci, které jsou užitečné pro prediktivní analýzu. sqlContext slouží k transformaci strukturovaných dat.

    schema = StructType([
    StructField("id", IntegerType(), False),
    StructField("name", StringType(), False),
    StructField("results", StringType(), False),
    StructField("violations", StringType(), True)])
    
    df = spark.createDataFrame(inspections.map(lambda l: (int(l[0]), l[1], l[12], l[13])) , schema)
    df.registerTempTable('CountResults')
    

    Čtyři sloupce, které mají zájem o datový rámec, jsou ID, název, výsledky a porušení.

  4. Spuštěním následujícího kódu získejte malou ukázku dat:

    df.show(5)
    

    Výstup je:

    +------+--------------------+-------+--------------------+
    |    id|                name|results|          violations|
    +------+--------------------+-------+--------------------+
    |413707|       LUNA PARK INC|   Fail|24. DISH WASHING ...|
    |391234|       CAFE SELMARIE|   Fail|2. FACILITIES TO ...|
    |413751|          MANCHU WOK|   Pass|33. FOOD AND NON-...|
    |413708|BENCHMARK HOSPITA...|   Pass|                    |
    |413722|           JJ BURGER|   Pass|                    |
    +------+--------------------+-------+--------------------+
    

Vysvětlení dat

Začněme získat představu o tom, co datová sada obsahuje.

  1. Spuštěním následujícího kódu zobrazte jedinečné hodnoty ve sloupci výsledků :

    df.select('results').distinct().show()
    

    Výstup je:

    +--------------------+
    |             results|
    +--------------------+
    |                Fail|
    |Business Not Located|
    |                Pass|
    |  Pass w/ Conditions|
    |     Out of Business|
    +--------------------+
    
  2. Spuštěním následujícího kódu vizualizujete distribuci těchto výsledků:

    %%sql -o countResultsdf
    SELECT COUNT(results) AS cnt, results FROM CountResults GROUP BY results
    

    Magie %%sql následovaná -o countResultsdf zajišťuje, že se výstup dotazu zachová místně na serveru Jupyter (obvykle hlavní uzel clusteru). Výstup je trvalý jako datový rámec Pandas se zadaným názvem countResultsdf. Další informace o %%sql magii a dalších magických funkcích dostupných s jádrem PySpark naleznete v tématu Jádra dostupná v poznámkových blocích Jupyter s clustery Apache Spark HDInsight.

    Výstup je:

    Výstup dotazu SQL

  3. K vytvoření grafu můžete použít také knihovnu Matplotlib, která se používá k vytvoření vizualizace dat. Vzhledem k tomu, že vykreslení musí být vytvořeno z místně trvalého datového rámce countResultsdf , musí fragment kódu začínat magií %%local . Tato akce zajistí, že se kód spustí místně na serveru Jupyter.

    %%local
    %matplotlib inline
    import matplotlib.pyplot as plt
    
    labels = countResultsdf['results']
    sizes = countResultsdf['cnt']
    colors = ['turquoise', 'seagreen', 'mediumslateblue', 'palegreen', 'coral']
    plt.pie(sizes, labels=labels, autopct='%1.1f%%', colors=colors)
    plt.axis('equal')
    

    Pokud chcete předpovědět výsledek kontroly potravin, musíte na základě porušení vyvinout model. Vzhledem k tomu, že logistická regrese je metoda binární klasifikace, dává smysl seskupit výsledná data do dvou kategorií: Fail a Pass:

    • Úspěšné absolvování

      • Úspěšné absolvování
      • Pass w/ conditions
    • Neúspěch

      • Neúspěch
    • Zahodit

      • Firma se nenachází
      • Mimo firmu

      Data s jinými výsledky ("Business Not Located" nebo "Out of Business") nejsou užitečná a přesto tvoří malé procento výsledků.

  4. Spuštěním následujícího kódu převeďte existující datový rámec(df) na nový datový rámec, ve kterém je každá kontrola reprezentována jako dvojice porušení popisků. V tomto případě popisek 0.0 představuje selhání, popisek 1.0 představuje úspěch a popisek -1.0 představuje některé výsledky kromě těchto dvou výsledků.

    def labelForResults(s):
        if s == 'Fail':
            return 0.0
        elif s == 'Pass w/ Conditions' or s == 'Pass':
            return 1.0
        else:
            return -1.0
    label = UserDefinedFunction(labelForResults, DoubleType())
    labeledData = df.select(label(df.results).alias('label'), df.violations).where('label >= 0')
    
  5. Spuštěním následujícího kódu zobrazte jeden řádek označených dat:

    labeledData.take(1)
    

    Výstup je:

    [Row(label=0.0, violations=u"41. PREMISES MAINTAINED FREE OF LITTER, UNNECESSARY ARTICLES, CLEANING  EQUIPMENT PROPERLY STORED - Comments: All parts of the food establishment and all parts of the property used in connection with the operation of the establishment shall be kept neat and clean and should not produce any offensive odors.  REMOVE MATTRESS FROM SMALL DUMPSTER. | 35. WALLS, CEILINGS, ATTACHED EQUIPMENT CONSTRUCTED PER CODE: GOOD REPAIR, SURFACES CLEAN AND DUST-LESS CLEANING METHODS - Comments: The walls and ceilings shall be in good repair and easily cleaned.  REPAIR MISALIGNED DOORS AND DOOR NEAR ELEVATOR.  DETAIL CLEAN BLACK MOLD LIKE SUBSTANCE FROM WALLS BY BOTH DISH MACHINES.  REPAIR OR REMOVE BASEBOARD UNDER DISH MACHINE (LEFT REAR KITCHEN). SEAL ALL GAPS.  REPLACE MILK CRATES USED IN WALK IN COOLERS AND STORAGE AREAS WITH PROPER SHELVING AT LEAST 6' OFF THE FLOOR.  | 38. VENTILATION: ROOMS AND EQUIPMENT VENTED AS REQUIRED: PLUMBING: INSTALLED AND MAINTAINED - Comments: The flow of air discharged from kitchen fans shall always be through a duct to a point above the roofline.  REPAIR BROKEN VENTILATION IN MEN'S AND WOMEN'S WASHROOMS NEXT TO DINING AREA. | 32. FOOD AND NON-FOOD CONTACT SURFACES PROPERLY DESIGNED, CONSTRUCTED AND MAINTAINED - Comments: All food and non-food contact equipment and utensils shall be smooth, easily cleanable, and durable, and shall be in good repair.  REPAIR DAMAGED PLUG ON LEFT SIDE OF 2 COMPARTMENT SINK.  REPAIR SELF CLOSER ON BOTTOM LEFT DOOR OF 4 DOOR PREP UNIT NEXT TO OFFICE.")]
    

Vytvoření modelu logistické regrese ze vstupního datového rámce

Posledním úkolem je převést označená data. Převeďte data do formátu analyzovaného logistickou regresí. Vstup do logistického regresního algoritmu potřebuje sadu dvojic vektorů funkce popisku. Kde "vektor funkce" je vektor čísel, který představuje vstupní bod. Proto je potřeba převést sloupec "porušení", který je částečně strukturovaný a obsahuje mnoho komentářů ve volném textu. Převeďte sloupec na pole skutečných čísel, kterým počítač snadno rozumí.

Jedním ze standardních přístupů strojového učení pro zpracování přirozeného jazyka je přiřazení jednotlivých slov indexu. Pak předejte vektor algoritmu strojového učení. Hodnota každého indexu obsahuje relativní frekvenci tohoto slova v textovém řetězci.

MLlib poskytuje snadný způsob, jak tuto operaci provést. Nejprve "tokenizujte" každý řetězec porušení, abyste získali jednotlivá slova v každém řetězci. Potom pomocí funkce HashingTF převeďte každou sadu tokenů na vektor funkce, který pak lze předat algoritmu logistické regrese k vytvoření modelu. Všechny tyto kroky provedete postupně pomocí kanálu.

tokenizer = Tokenizer(inputCol="violations", outputCol="words")
hashingTF = HashingTF(inputCol=tokenizer.getOutputCol(), outputCol="features")
lr = LogisticRegression(maxIter=10, regParam=0.01)
pipeline = Pipeline(stages=[tokenizer, hashingTF, lr])

model = pipeline.fit(labeledData)

Vyhodnocení modelu pomocí jiné datové sady

Model, který jste vytvořili dříve, můžete použít k predikci výsledků nových kontrol. Předpovědi jsou založeny na pozorovaných porušeních. Tento model jste vytrénovali na Food_Inspections1.csv datové sady. K vyhodnocení síly tohoto modelu u nových dat můžete použít druhou datovou sadu Food_Inspections2.csv. Tato druhá datová sada (Food_Inspections2.csv) je ve výchozím kontejneru úložiště přidruženém ke clusteru.

  1. Spuštěním následujícího kódu vytvořte nový datový rámec, predictionsDf obsahující predikci vygenerovanou modelem. Fragment kódu také vytvoří dočasnou tabulku s názvem Predictions (Předpovědi) na základě datového rámce.

    testData = sc.textFile('wasbs:///HdiSamples/HdiSamples/FoodInspectionData/Food_Inspections2.csv')\
                .map(csvParse) \
                .map(lambda l: (int(l[0]), l[1], l[12], l[13]))
    testDf = spark.createDataFrame(testData, schema).where("results = 'Fail' OR results = 'Pass' OR results = 'Pass w/ Conditions'")
    predictionsDf = model.transform(testDf)
    predictionsDf.registerTempTable('Predictions')
    predictionsDf.columns
    

    Měl by se zobrazit výstup podobný následujícímu textu:

    ['id',
        'name',
        'results',
        'violations',
        'words',
        'features',
        'rawPrediction',
        'probability',
        'prediction']
    
  2. Podívejte se na jednu z předpovědí. Spusťte tento fragment kódu:

    predictionsDf.take(1)
    

    V testovací sadě dat je předpověď pro první položku.

  3. Metoda model.transform() použije stejnou transformaci na všechna nová data se stejným schématem a dorazí na předpověď, jak klasifikovat data. Pomocí statistik můžete získat představu o tom, jak byly předpovědi:

    numSuccesses = predictionsDf.where("""(prediction = 0 AND results = 'Fail') OR
                                            (prediction = 1 AND (results = 'Pass' OR
                                                                results = 'Pass w/ Conditions'))""").count()
    numInspections = predictionsDf.count()
    
    print ("There were", numInspections, "inspections and there were", numSuccesses, "successful predictions")
    print ("This is a", str((float(numSuccesses) / float(numInspections)) * 100) + "%", "success rate")
    

    Výstup vypadá jako následující text:

    There were 9315 inspections and there were 8087 successful predictions
    This is a 86.8169618894% success rate
    

    Použití logistické regrese se Sparkem poskytuje model vztahu mezi popisy porušení v angličtině. A jestli daná firma projde nebo selžou kontrolu potravin.

Vytvoření vizuální reprezentace předpovědi

Teď můžete vytvořit konečnou vizualizaci, která vám pomůže zdůvodnění výsledků tohoto testu.

  1. Začnete extrahováním různých předpovědí a výsledků z dočasné tabulky Predictions vytvořené dříve. Následující dotazy rozdělí výstup jako true_positive, false_positive, true_negative a false_negative. V následujících dotazech vypnete vizualizaci pomocí -q a uložíte výstup (pomocí ) -ojako datové rámce, které se pak dají použít s %%local magií.

    %%sql -q -o true_positive
    SELECT count(*) AS cnt FROM Predictions WHERE prediction = 0 AND results = 'Fail'
    
    %%sql -q -o false_positive
    SELECT count(*) AS cnt FROM Predictions WHERE prediction = 0 AND (results = 'Pass' OR results = 'Pass w/ Conditions')
    
    %%sql -q -o true_negative
    SELECT count(*) AS cnt FROM Predictions WHERE prediction = 1 AND results = 'Fail'
    
    %%sql -q -o false_negative
    SELECT count(*) AS cnt FROM Predictions WHERE prediction = 1 AND (results = 'Pass' OR results = 'Pass w/ Conditions')
    
  2. Nakonec pomocí následujícího fragmentu kódu vygenerujte graf pomocí knihovny Matplotlib.

    %%local
    %matplotlib inline
    import matplotlib.pyplot as plt
    
    labels = ['True positive', 'False positive', 'True negative', 'False negative']
    sizes = [true_positive['cnt'], false_positive['cnt'], false_negative['cnt'], true_negative['cnt']]
    colors = ['turquoise', 'seagreen', 'mediumslateblue', 'palegreen', 'coral']
    plt.pie(sizes, labels=labels, autopct='%1.1f%%', colors=colors)
    plt.axis('equal')
    

    Měl by se zobrazit následující výstup:

    Výstup aplikace strojového učení Sparku – procenta neúspěšných kontrol potravin ve výsečovém grafu

    V tomto grafu "pozitivní" výsledek odkazuje na neúspěšnou kontrolu potravin, zatímco negativní výsledek odkazuje na úspěšnou kontrolu.

Vypnutí poznámkového bloku

Po spuštění aplikace byste měli poznámkový blok vypnout a uvolnit prostředky. Provedete to tak, že v nabídce Soubor poznámkového bloku vyberete Zavřít a zastavit. Tato akce poznámkový blok vypne a zavře.

Další kroky