PySpark สำหรับการประมวลผลภาษาธรรมชาติบน Dataproc

1. ภาพรวม

การประมวลผลภาษาธรรมชาติ (NLP) คือการศึกษาในการหาข้อมูลเชิงลึกและทำการวิเคราะห์ข้อมูลแบบข้อความ เนื่องจากปริมาณงานเขียนที่สร้างขึ้นบนอินเทอร์เน็ตเพิ่มขึ้นอย่างต่อเนื่อง ปัจจุบันองค์กรต่างๆ จึงพยายามใช้ข้อความของตนเพื่อให้ได้ข้อมูลที่เกี่ยวข้องกับธุรกิจของตนมากกว่าที่เคย

NLP สามารถนำไปใช้ได้ทุกอย่างตั้งแต่การแปลภาษา การวิเคราะห์ความรู้สึก ไปจนถึงการสร้างประโยคตั้งแต่ต้น และอื่นๆ อีกมากมาย นี่คืองานวิจัยที่กำลังดำเนินอยู่ซึ่งกำลังเปลี่ยนแปลงวิธีที่เราทำงานกับข้อความ

เราจะสำรวจวิธีใช้ NLP กับข้อมูลข้อความจำนวนมากในปริมาณมาก งานนี้อาจทำได้ยากมาก โชคดีที่เราใช้ประโยชน์จากไลบรารีต่างๆ เช่น Spark MLlib และ spark-nlp เพื่อทำให้ง่ายขึ้น

2. กรณีการใช้งานของเรา

หัวหน้านักวิทยาศาสตร์ข้อมูลแห่ง "FoodCorp" ซึ่งเป็นองค์กรของเรา (สมมติ) ของเรา สนใจดูข้อมูลเพิ่มเติมเกี่ยวกับเทรนด์ในอุตสาหกรรมอาหาร เรามีสิทธิ์เข้าถึงคลังข้อมูลข้อความในรูปแบบของโพสต์จาก Subreddit r/food ของ Reddit ซึ่งเราจะใช้เพื่อสำรวจสิ่งที่ผู้คนพูดถึง

แนวทางหนึ่งในการดำเนินการนี้คือการใช้ NLP ที่เรียกว่า "การสร้างแบบจำลองหัวข้อ" การจำลองหัวข้อคือวิธีการทางสถิติที่ระบุแนวโน้มในความหมายเชิงอรรถศาสตร์ของกลุ่มเอกสารได้ กล่าวคือ เราสร้างโมเดลหัวข้อในคลังข้อมูล "โพสต์" ของ Reddit ได้ ซึ่งจะสร้างรายการ "หัวข้อ" หรือกลุ่มคำที่อธิบายเทรนด์

ในการสร้างโมเดล เราจะใช้อัลกอริทึมที่เรียกว่า Latent Dirichlet Allocation (LDA) ซึ่งมักใช้เพื่อจัดกลุ่มข้อความ ดูการแนะนำที่ยอดเยี่ยมเกี่ยวกับ LDA ได้ที่นี่

3. การสร้างโปรเจ็กต์

หากยังไม่มีบัญชี Google (Gmail หรือ Google Apps) คุณต้องสร้างบัญชีก่อน ลงชื่อเข้าใช้คอนโซล Google Cloud Platform ( console.cloud.google.com) และสร้างโปรเจ็กต์ใหม่

7e541d932b20c074.png

2deefc9295d114ea.png

ภาพหน้าจอจากวันที่ 10-02-2016 เวลา 12:45:26.png

ถัดไป คุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร Google Cloud

การใช้งาน Codelab นี้น่าจะมีค่าใช้จ่ายไม่เกิน 2-3 ดอลลาร์ แต่อาจมากกว่านี้หากคุณตัดสินใจใช้ทรัพยากรมากขึ้นหรือปล่อยให้ทำงานต่อไป Codelab ของ PySpark-BigQuery และ Spark-NLP จะอธิบายกระบวนการ "ล้างข้อมูล" ในช่วงท้าย

ผู้ใช้ใหม่ของ Google Cloud Platform มีสิทธิ์รับช่วงทดลองใช้ฟรี$300

4. การจัดตั้งสภาพแวดล้อมของเรา

ก่อนอื่น เราต้องเปิดใช้ Dataproc และ API ของ Compute Engine

คลิกไอคอนเมนูที่ด้านซ้ายบนของหน้าจอ

2bfc27ef9ba2ec7d.png

เลือกตัวจัดการ API จากเมนูแบบเลื่อนลง

408af5f32c4b7c25.png

คลิกเปิดใช้ API และบริการ

a9c0e84296a7ba5b.png

ค้นหา "Compute Engine" ในช่องค้นหา คลิกที่ "Google Compute Engine API" ในรายการผลลัพธ์ที่ปรากฏขึ้น

b6adf859758d76b3.png

คลิกเปิดใช้ในหน้า Google Compute Engine

da5584a1cbc77104.png

เมื่อเปิดใช้แล้ว ให้คลิกลูกศรที่ชี้ไปทางซ้ายเพื่อย้อนกลับ

ค้นหา "Google Dataproc API" และเปิดใช้ด้วย

f782195d8e3d732a.png

จากนั้นเปิด Cloud Shell โดยการคลิกปุ่มที่มุมขวาบนของ Cloud Console

a10c47ee6ca41c54.png

เราจะตั้งค่าตัวแปรสภาพแวดล้อมที่ใช้อ้างอิงขณะทำงานกับ Codelab ได้ ก่อนอื่นให้เลือกชื่อสำหรับคลัสเตอร์ Dataproc ที่เรากำลังจะสร้าง เช่น "my-cluster" แล้วตั้งชื่อในสภาพแวดล้อมของคุณ โดยสามารถใช้ชื่อใดก็ได้ตามต้องการ

CLUSTER_NAME=my-cluster

จากนั้นให้เลือกโซนจากโซนที่พร้อมใช้งานที่นี่ ตัวอย่างเช่น us-east1-b.

REGION=us-east1

สุดท้าย เราจะต้องตั้งค่าที่เก็บข้อมูลต้นทางที่งานของเราจะอ่านข้อมูล เรามีข้อมูลตัวอย่างอยู่ในที่เก็บข้อมูล bm_reddit แต่คุณสามารถใช้ข้อมูลที่คุณสร้างขึ้นจาก PySpark สำหรับการประมวลผลข้อมูล BigQuery ล่วงหน้า หากคุณเคยดำเนินการมาก่อนแล้ว

BUCKET_NAME=bm_reddit

เมื่อกำหนดค่าตัวแปรสภาพแวดล้อมแล้ว ให้เรียกใช้คำสั่งต่อไปนี้เพื่อสร้างคลัสเตอร์ Dataproc ของเรา

 gcloud beta dataproc clusters create ${CLUSTER_NAME} \
     --region ${REGION} \
     --metadata 'PIP_PACKAGES=google-cloud-storage spark-nlp==2.7.2' \
     --worker-machine-type n1-standard-8 \
     --num-workers 4 \
     --image-version 1.4-debian10 \
     --initialization-actions gs://dataproc-initialization-actions/python/pip-install.sh \
     --optional-components=JUPYTER,ANACONDA \
     --enable-component-gateway

เรามาดูแต่ละคำสั่งต่อไปนี้กัน

gcloud beta dataproc clusters create ${CLUSTER_NAME}: จะเริ่มต้นการสร้างคลัสเตอร์ Dataproc ด้วยชื่อที่คุณระบุก่อนหน้านี้ เรารวม beta ไว้ที่นี่เพื่อเปิดใช้ฟีเจอร์เบต้าของ Dataproc เช่น เกตเวย์คอมโพเนนต์ ซึ่งเราอธิบายไว้ด้านล่าง

--zone=${ZONE}: ตั้งค่าตำแหน่งคลัสเตอร์

--worker-machine-type n1-standard-8: นี่คือประเภทของเครื่องที่ใช้สำหรับผู้ปฏิบัติงานของเรา

--num-workers 4: เราจะมีผู้ปฏิบัติงาน 4 คนในคลัสเตอร์ของเรา

--image-version 1.4-debian9: หมายถึง Dataproc เวอร์ชันอิมเมจที่เราจะใช้

--initialization-actions ...: การดำเนินการเริ่มต้นเป็นสคริปต์ที่กำหนดเองซึ่งจะดำเนินการเมื่อสร้างคลัสเตอร์และผู้ปฏิบัติงาน โดยอาจเป็นเนื้อหาที่ผู้ใช้สร้างขึ้นและจัดเก็บไว้ในที่เก็บข้อมูล GCS หรืออ้างอิงจากที่เก็บข้อมูลสาธารณะ dataproc-initialization-actions ก็ได้ การดำเนินการเริ่มต้นที่ระบุไว้ที่นี่จะอนุญาตให้ติดตั้งแพ็กเกจ Python โดยใช้ Pip ตามที่ให้ไว้กับ Flag --metadata

--metadata 'PIP_PACKAGES=google-cloud-storage spark-nlp': รายการแพ็กเกจที่คั่นด้วยช่องว่างสำหรับติดตั้งใน Dataproc ในกรณีนี้ เราจะติดตั้งไลบรารีของไคลเอ็นต์ Python google-cloud-storage และ spark-nlp

--optional-components=ANACONDA: คอมโพเนนต์ที่ไม่บังคับคือแพ็กเกจทั่วไปที่ใช้กับ Dataproc ซึ่งจะติดตั้งบนคลัสเตอร์ Dataproc โดยอัตโนมัติระหว่างการสร้าง ข้อดีของการใช้คอมโพเนนต์ที่ไม่บังคับเหนือการดำเนินการเริ่มต้นรวมถึงเวลาเริ่มต้นที่เร็วขึ้นและได้รับการทดสอบสำหรับ Dataproc บางเวอร์ชัน โดยรวมแล้ว มีความเชื่อถือได้มากกว่า

--enable-component-gateway: แฟล็กนี้ช่วยให้เราสามารถใช้ประโยชน์จากเกตเวย์คอมโพเนนต์ของ Dataproc เพื่อดู UI ทั่วไป เช่น Zeppelin, Jupyter หรือ Spark History หมายเหตุ: บางส่วนของรายการเหล่านี้ต้องใช้คอมโพเนนต์ที่ไม่บังคับที่เกี่ยวข้อง

โปรดดู Codelab สำหรับข้อมูลเบื้องต้นเกี่ยวกับ Dataproc แบบเจาะลึกมากขึ้น

จากนั้นเรียกใช้คำสั่งต่อไปนี้ใน Cloud Shell เพื่อโคลนที่เก็บด้วยโค้ดตัวอย่างและเข้าสู่ไดเรกทอรีที่ถูกต้อง

cd
git clone https://github.com/GoogleCloudPlatform/cloud-dataproc
cd cloud-dataproc/codelabs/spark-nlp

5. ประกาย MLlib

Spark MLlib เป็นไลบรารีแมชชีนเลิร์นนิงที่รองรับการปรับขนาดซึ่งเขียนขึ้นใน Apache Spark MLlib ใช้ประโยชน์จากประสิทธิภาพของ Spark ที่มีชุดอัลกอริทึมของแมชชีนเลิร์นนิงที่ได้รับการปรับแต่งอย่างละเอียด ทำให้สามารถวิเคราะห์ข้อมูลจำนวนมาก มี API ใน Java, Scala, Python และ R. ใน Codelab นี้ เราจะมุ่งเน้นที่ Python โดยเฉพาะ

MLlib มีตัวแปลงและตัวประมาณจำนวนมาก Transformer เป็นเครื่องมือที่สามารถเปลี่ยนแปลงหรือเปลี่ยนแปลงข้อมูลของคุณ โดยทั่วไปจะมีฟังก์ชัน transform() ขณะที่เครื่องมือประมาณเป็นอัลกอริทึมที่สร้างไว้ล่วงหน้าซึ่งใช้ในการฝึกข้อมูล ซึ่งโดยทั่วไปจะมีฟังก์ชัน fit()

ตัวอย่างของ Transformer ได้แก่

  • การแปลงข้อมูลเป็นโทเค็น (การสร้างเวกเตอร์ของตัวเลขจากสตริงคำ)
  • การเข้ารหัสแบบฮอตเดียว (สร้างเวกเตอร์แบบกระจัดกระจายของตัวเลขที่แสดงถึงคำที่มีอยู่ในสตริง)
  • ตัวลบคำหยุด (นำคำที่ไม่ได้เพิ่มมูลค่าทางความหมายในสตริงออก)

ตัวอย่างของเครื่องมือประมาณการมีดังนี้

  • การจำแนกประเภท (นี่คือแอปเปิลหรือส้ม)
  • การถดถอย (แอปเปิ้ลนี้ควรมีค่าใช้จ่ายเท่าใด)
  • การจัดกลุ่ม (แอปเปิ้ลทั้งหมดคล้ายกันแค่ไหน)
  • ต้นไม้การตัดสินใจ (ถ้าเป็นสี == ส้ม แสดงว่าเป็นสีส้ม ไม่อย่างนั้นจะเป็นแอปเปิ้ล)
  • การลดมิติข้อมูล (เราสามารถนำฟีเจอร์ออกจากชุดข้อมูลและยังคงแยกความแตกต่างระหว่างแอปเปิลกับส้มได้ไหม)

นอกจากนี้ MLlib ยังมีเครื่องมือสำหรับวิธีการอื่นๆ ที่ใช้กันโดยทั่วไปในแมชชีนเลิร์นนิง เช่น การปรับแต่งและการเลือกไฮเปอร์พารามิเตอร์ ตลอดจนการตรวจสอบข้ามอุปกรณ์

นอกจากนี้ MLlib ยังมี Pipelines API ที่ให้คุณสร้างไปป์ไลน์การเปลี่ยนรูปแบบข้อมูลโดยใช้ตัวเปลี่ยนรูปแบบต่างๆ ที่จะเรียกใช้อีกครั้งได้

6. Spark-NLP

Spark-nlp เป็นไลบรารีที่ John Snow Labs สร้างขึ้นเพื่อการใช้งานการประมวลผลภาษาธรรมชาติที่มีประสิทธิภาพโดยใช้ Spark โดยจะมีเครื่องมือในตัวที่เรียกว่าคำอธิบายประกอบสำหรับงานทั่วไป เช่น

  • การแปลงข้อมูลเป็นโทเค็น (การสร้างเวกเตอร์ของตัวเลขจากสตริงคำ)
  • สร้างการฝังคำ (กำหนดความสัมพันธ์ระหว่างคำผ่านเวกเตอร์)
  • แท็กชนิดของเสียงพูด (คำใดเป็นคำนาม คำกริยาคืออะไรบ้าง)

แม้อยู่นอกขอบเขตของ Codelab นี้ spark-nlp ก็ยังผสานรวมกับ TensorFlow ได้ดีด้วย

Spark-NLP อาจขยายขอบเขตความสามารถของ Spark MLlib ด้วยการจัดหาคอมโพเนนต์ที่นำไปใช้ใน MLlib Pipelines ได้อย่างง่ายดาย

7. แนวทางปฏิบัติแนะนำสำหรับการประมวลผลภาษาธรรมชาติ

ก่อนที่เราจะแยกข้อมูลที่มีประโยชน์ออกมาได้ เราจำเป็นต้องดูแลรายละเอียดบางอย่าง ขั้นตอนการประมวลผลข้อมูลล่วงหน้ามีดังนี้

การแปลงข้อมูลเป็นโทเค็น

สิ่งแรกที่เรามักทำกันคือ "โทเค็น" ข้อมูลดังกล่าว ซึ่งเกี่ยวข้องกับการนำข้อมูลและแยกข้อมูลออกตาม "โทเค็น" หรือคำต่างๆ โดยทั่วไป เราจะลบเครื่องหมายวรรคตอนและตั้งค่าคำทั้งหมดให้เป็นตัวพิมพ์เล็กในขั้นตอนนี้ ตัวอย่างเช่น สมมติว่าเรามีสตริงต่อไปนี้ What time is it? หลังจากการแปลงข้อมูลเป็นโทเค็น ประโยคนี้จะประกอบด้วยโทเค็น 4 รายการ: "what" , "time", "is", "it". เราไม่ต้องการให้โมเดลถือว่าคำว่า what เป็นคำ 2 คำที่มีการใช้อักษรตัวพิมพ์ใหญ่ 2 ตัวที่แตกต่างกัน นอกจากนี้ เครื่องหมายวรรคตอนมักจะไม่ช่วยให้เราเรียนรู้การอนุมานจากคำได้ดีขึ้น เราจึงตัดคำนั้นออกได้เช่นกัน

การปรับให้สอดคล้องตามมาตรฐาน

เรามักต้องการ "ทำให้เป็นมาตรฐาน" ข้อมูลดังกล่าว การดำเนินการนี้จะแทนที่คำที่มีความหมายคล้ายกันด้วยสิ่งเดียวกัน เช่น ถ้าคำว่า "ต่อสู้" "ต่อสู้" และ "ดวล" ถูกระบุในข้อความ การปรับให้เป็นมาตรฐานอาจแทนที่ "ต่อสู้" และ "ดวล" ที่มีคำว่า "ต่อสู้"

การตัดคำ

คำจากรากคำเดียวกันจะแทนที่คำที่มีความหมายรากของคำนั้น เช่น คำว่า "รถยนต์" "รถยนต์" และ "รถยนต์" จะแทนที่ด้วยคำว่า "รถยนต์" เนื่องจากคำเหล่านี้ทั้งหมดบ่งบอกถึงสิ่งเดียวกันที่ราก

การนำคำหยุดออก

คำหยุดคือคำต่างๆ เช่น "และ" และ "the" ที่มักไม่ได้เพิ่มคุณค่าให้กับความหมายในเชิงอรรถศาสตร์ของประโยค โดยปกติแล้วเราจะนำข้อความเหล่านี้ออกเพื่อลดเสียงรบกวนในชุดข้อมูลข้อความ

8. การทำงานไปเรื่อยๆ

ลองมาดูงานที่เราจะทำกัน คุณดูโค้ดได้ที่ cloud-dataproc/codelabs/spark-nlp/topic_model.py ใช้เวลาอย่างน้อยหลายนาทีในการอ่านและอ่านความคิดเห็นที่เกี่ยวข้องเพื่อทำความเข้าใจสิ่งที่เกิดขึ้น นอกจากนี้เราจะไฮไลต์ส่วนต่างๆ ด้านล่างนี้

# Python imports
import sys

# spark-nlp components. Each one is incorporated into our pipeline.
from sparknlp.annotator import Lemmatizer, Stemmer, Tokenizer, Normalizer
from sparknlp.base import DocumentAssembler, Finisher

# A Spark Session is how we interact with Spark SQL to create Dataframes
from pyspark.sql import SparkSession

# These allow us to create a schema for our data
from pyspark.sql.types import StructField, StructType, StringType, LongType

# Spark Pipelines allow us to sequentially add components such as transformers
from pyspark.ml import Pipeline

# These are components we will incorporate into our pipeline.
from pyspark.ml.feature import StopWordsRemover, CountVectorizer, IDF

# LDA is our model of choice for topic modeling
from pyspark.ml.clustering import LDA

# Some transformers require the usage of other Spark ML functions. We import them here
from pyspark.sql.functions import col, lit, concat

# This will help catch some PySpark errors
from pyspark.sql.utils import AnalysisException

# Assign bucket where the data lives
try:
    bucket = sys.argv[1]
except IndexError:
    print("Please provide a bucket name")
    sys.exit(1)

# Create a SparkSession under the name "reddit". Viewable via the Spark UI
spark = SparkSession.builder.appName("reddit topic model").getOrCreate()

# Create a three column schema consisting of two strings and a long integer
fields = [StructField("title", StringType(), True),
          StructField("body", StringType(), True),
          StructField("created_at", LongType(), True)]
schema = StructType(fields)

# We'll attempt to process every year / month combination below.
years = ['2016', '2017', '2018', '2019']
months = ['01', '02', '03', '04', '05', '06',
          '07', '08', '09', '10', '11', '12']

# This is the subreddit we're working with.
subreddit = "food"

# Create a base dataframe.
reddit_data = spark.createDataFrame([], schema)

# Keep a running list of all files that will be processed
files_read = []

for year in years:
    for month in months:

        # In the form of <project-id>.<dataset>.<table>
        gs_uri = f"gs://{bucket}/reddit_posts/{year}/{month}/{subreddit}.csv.gz"

        # If the table doesn't exist we will simply continue and not
        # log it into our "tables_read" list
        try:
            reddit_data = (
                spark.read.format('csv')
                .options(codec="org.apache.hadoop.io.compress.GzipCodec")
                .load(gs_uri, schema=schema)
                .union(reddit_data)
            )

            files_read.append(gs_uri)

        except AnalysisException:
            continue

if len(files_read) == 0:
    print('No files read')
    sys.exit(1)

# Replacing null values with their respective typed-equivalent is usually
# easier to work with. In this case, we'll replace nulls with empty strings.
# Since some of our data doesn't have a body, we can combine all of the text
# for the titles and bodies so that every row has useful data.

df_train = (
    reddit_data
    # Replace null values with an empty string
    .fillna("")
    .select(
         # Combine columns
        concat(
            # First column to concatenate. col() is used to specify that we're referencing a column
            col("title"),
            # Literal character that will be between the concatenated columns.
            lit(" "),
            # Second column to concatenate.
            col("body")
        # Change the name of the new column
        ).alias("text")
    )
)

# Now, we begin assembling our pipeline. Each component here is used to some transformation to the data.
# The Document Assembler takes the raw text data and convert it into a format that can
# be tokenized. It becomes one of spark-nlp native object types, the "Document".
document_assembler = DocumentAssembler().setInputCol("text").setOutputCol("document")

# The Tokenizer takes data that is of the "Document" type and tokenizes it.
# While slightly more involved than this, this is effectively taking a string and splitting
# it along ths spaces, so each word is its own string. The data then becomes the
# spark-nlp native type "Token".
tokenizer = Tokenizer().setInputCols(["document"]).setOutputCol("token")

# The Normalizer will group words together based on similar semantic meaning.
normalizer = Normalizer().setInputCols(["token"]).setOutputCol("normalizer")

# The Stemmer takes objects of class "Token" and converts the words into their
# root meaning. For instance, the words "cars", "cars'" and "car's" would all be replaced
# with the word "car".
stemmer = Stemmer().setInputCols(["normalizer"]).setOutputCol("stem")

# The Finisher signals to spark-nlp allows us to access the data outside of spark-nlp
# components. For instance, we can now feed the data into components from Spark MLlib.
finisher = Finisher().setInputCols(["stem"]).setOutputCols(["to_spark"]).setValueSplitSymbol(" ")

# Stopwords are common words that generally don't add much detail to the meaning
# of a body of text. In English, these are mostly "articles" such as the words "the"
# and "of".
stopword_remover = StopWordsRemover(inputCol="to_spark", outputCol="filtered")

# Here we implement TF-IDF as an input to our LDA model. CountVectorizer (TF) keeps track
# of the vocabulary that's being created so we can map our topics back to their
# corresponding words.
# TF (term frequency) creates a matrix that counts how many times each word in the
# vocabulary appears in each body of text. This then gives each word a weight based
# on its frequency.
tf = CountVectorizer(inputCol="filtered", outputCol="raw_features")

# Here we implement the IDF portion. IDF (Inverse document frequency) reduces
# the weights of commonly-appearing words.
idf = IDF(inputCol="raw_features", outputCol="features")

# LDA creates a statistical representation of how frequently words appear
# together in order to create "topics" or groups of commonly appearing words.
lda = LDA(k=10, maxIter=10)

# We add all of the transformers into a Pipeline object. Each transformer
# will execute in the ordered provided to the "stages" parameter
pipeline = Pipeline(
    stages = [
        document_assembler,
        tokenizer,
        normalizer,
        stemmer,
        finisher,
        stopword_remover,
        tf,
        idf,
        lda
    ]
)

# We fit the data to the model.
model = pipeline.fit(df_train)

# Now that we have completed a pipeline, we want to output the topics as human-readable.
# To do this, we need to grab the vocabulary generated from our pipeline, grab the topic
# model and do the appropriate mapping.  The output from each individual component lives
# in the model object. We can access them by referring to them by their position in
# the pipeline via model.stages[<ind>]

# Let's create a reference our vocabulary.
vocab = model.stages[-3].vocabulary

# Next, let's grab the topics generated by our LDA model via describeTopics(). Using collect(),
# we load the output into a Python array.
raw_topics = model.stages[-1].describeTopics().collect()

# Lastly, let's get the indices of the vocabulary terms from our topics
topic_inds = [ind.termIndices for ind in raw_topics]

# The indices we just grab directly map to the term at position <ind> from our vocabulary.
# Using the below code, we can generate the mappings from our topic indices to our vocabulary.
topics = []
for topic in topic_inds:
    _topic = []
    for ind in topic:
        _topic.append(vocab[ind])
    topics.append(_topic)

# Let's see our topics!
for i, topic in enumerate(topics, start=1):
    print(f"topic {i}: {topic}")

การเรียกใช้งาน

มาลองทำงานของเรากันเลย เรียกใช้คำสั่งต่อไปนี้ได้เลย

gcloud dataproc jobs submit pyspark --cluster ${CLUSTER_NAME}\
    --region ${REGION}\
    --properties=spark.jars.packages=com.johnsnowlabs.nlp:spark-nlp_2.11:2.7.2\
    --driver-log-levels root=FATAL \
    topic_model.py \
    -- ${BUCKET_NAME}

คำสั่งนี้ช่วยให้เราใช้ประโยชน์จาก Dataproc Jobs API ได้ การรวมคำสั่ง pyspark จะทำให้คลัสเตอร์ทราบว่านี่เป็นงาน PySpark เราให้ชื่อคลัสเตอร์ พารามิเตอร์ที่ไม่บังคับจากที่มีอยู่ที่นี่ และชื่อไฟล์ที่มีงานนั้น ในกรณีของเรา ให้ระบุพารามิเตอร์ --properties ซึ่งทำให้เราเปลี่ยนพร็อพเพอร์ตี้ต่างๆ ของ Spark, Yarn หรือ Dataproc ได้ เรากำลังจะเปลี่ยนแปลงพร็อพเพอร์ตี้ Spark packages ซึ่งทำให้เราแจ้ง Spark ได้ว่าเราต้องการรวม spark-nlp เป็นแพ็กเกจตามงานของเรา นอกจากนี้เรายังมีพารามิเตอร์ --driver-log-levels root=FATAL ซึ่งจะระงับเอาต์พุตของบันทึกส่วนใหญ่จาก PySpark ยกเว้นข้อผิดพลาด โดยทั่วไป บันทึกของ Spark มักจะมีเสียงดัง

สุดท้าย -- ${BUCKET} คืออาร์กิวเมนต์บรรทัดคำสั่งสำหรับสคริปต์ Python ที่มีชื่อที่เก็บข้อมูล จดช่องว่างระหว่าง -- ถึง ${BUCKET}

หลังจากเรียกใช้งานได้ 2-3 นาที เราควรเห็นเอาต์พุตที่มีโมเดลของเรา:

167f4c839385dcf0.png

เยี่ยมเลย คุณอนุมานแนวโน้มโดยดูที่ผลลัพธ์จากโมเดลได้ไหม แล้วของเราล่ะ

จากผลลัพธ์ข้างต้น อาจอนุมานเทรนด์จากหัวข้อ 8 เกี่ยวกับอาหารเช้าและของหวานจากหัวข้อ 9

9. ล้างข้อมูล

เพื่อหลีกเลี่ยงการเรียกเก็บเงินที่ไม่จำเป็นในบัญชี GCP หลังจากการเริ่มต้นอย่างรวดเร็วนี้เสร็จสิ้นแล้ว ให้ทำดังนี้

  1. ลบที่เก็บข้อมูล Cloud Storage สำหรับสภาพแวดล้อมและที่คุณสร้างขึ้น
  2. ลบสภาพแวดล้อม Dataproc

หากสร้างโปรเจ็กต์สำหรับ Codelab นี้โดยเฉพาะ คุณจะเลือกลบโปรเจ็กต์ได้ด้วย โดยทำดังนี้

  1. ในคอนโซล GCP ให้ไปที่หน้าโปรเจ็กต์
  2. ในรายการโปรเจ็กต์ ให้เลือกโปรเจ็กต์ที่ต้องการลบ แล้วคลิกลบ
  3. ในช่อง ให้พิมพ์รหัสโปรเจ็กต์ แล้วคลิกปิดเครื่องเพื่อลบโปรเจ็กต์

ใบอนุญาต

ผลงานนี้ได้รับอนุญาตภายใต้ใบอนุญาตครีเอทีฟคอมมอนส์แบบระบุแหล่งที่มา 3.0 และใบอนุญาต Apache 2.0