ด้วยรหัสใน python สำหรับการจำแนกข้อความ

หลังจากครอบคลุม AutoML สำหรับการจำแนกประเภทและการถดถอยโดยใช้ "MLJAR" และการคาดการณ์อนุกรมเวลาโดยใช้ "AutoTS" ครั้งนี้ ฉันมีโอกาสทำงานกับการจัดหมวดหมู่แบบหลายป้ายกำกับ (ไม่ใช่แบบหลายคลาส) หากต้องการลองสิ่งใหม่ๆ ฉันจึงใช้ googled auto-ml สำหรับการจัดประเภทแบบหลายป้ายกำกับ และหลังจากเจาะลึกมาบ้าง ฉันก็รู้เกี่ยวกับ Ludwig ซึ่งเป็นกรอบการเรียนรู้ของเครื่องจักรที่เปิดเผยซึ่งสามารถใช้สำหรับการจัดประเภทแบบหลายป้ายกำกับได้

เอาล่ะ มาเริ่มกันเลย

แต่ก่อนที่จะกระโดดไปข้างหน้า

ระบบการเรียนรู้ของเครื่องที่ประกาศคืออะไร?

ดังนั้นระบบ ML อาจมีหลายประเภท

  • ยืดหยุ่น: ในระบบดังกล่าว dev เขียนโค้ดทุกอย่างตั้งแต่ต้นโดยใช้ไลบรารี เช่น TensorFlow, Keras และ PyTorch โดยใช้ยูทิลิตี้ที่ไลบรารีเหล่านี้มอบให้ กล่าวคือ คุณเป็นผู้ตัดสินใจในทุกรายละเอียดของสถาปัตยกรรมที่คุณต้องการจะมี แต่ จับได้ว่าคุณกำลังจะเขียนโค้ดเยอะมาก ตัวอย่างอาจเป็นโครงข่ายประสาทเทียมที่คุณออกแบบโดยใช้ Tensorflow หรือ Keras ตั้งแต่เริ่มต้น
  • AutoML:ใน AutoML นักพัฒนาซอฟต์แวร์ไม่ได้ทำอะไรเลยนอกจากนั่งเบาะหลังอย่างเต็มที่ สถาปัตยกรรม AutoML มีหน้าที่ดูแลทุกอย่าง เลือกรุ่นอะไร และประมวลผลล่วงหน้าอะไรให้เสร็จ ทุกอย่าง!! สิ่งเดียวที่จับได้คือความยืดหยุ่นต่ำมากกับระบบดังกล่าว และผู้พัฒนาไม่สามารถปรับแต่งได้มากนัก
  • ระบบที่ประกาศ:เป็นจุดกึ่งกลางระหว่างระบบยืดหยุ่นและระบบ AutoML ซึ่งนักพัฒนาสามารถเลือกส่วนประกอบต่างๆ ของไปป์ไลน์ (แม้ว่าจะไม่จำเป็นต้องเขียนโค้ดก็ตาม) ในขณะที่สิ่งใดก็ตามที่ไม่ได้ระบุจะไปที่ส่วน AutoML ของ ระบบ. ดังนั้น ระบบที่ประกาศจะรักษาการแลกเปลี่ยนระหว่างความยืดหยุ่นกับ AutoML ลุดวิกก็เป็นหนึ่งในระบบดังกล่าว

หากต้องการคุณสามารถระบุทุกรายละเอียดของไปป์ไลน์ได้ หากไม่ต้องการ ทุกอย่างจะได้รับการดูแลโดยระบบ AutoML ของ Ludwig เรียบง่าย !!

ดังนั้น เพื่อไม่ให้เป็นการเสียเวลา เรามาจัดการกับลุดวิกกันดีกว่า

ฉันจะใช้ ชุดข้อมูลนี้ สำหรับส่วนที่เหลือของโพสต์ แตกไฟล์นี้แล้วอ่าน train.csv

  1. นำเข้าไลบรารีที่จำเป็นและโหลดชุดข้อมูล
#pip3 install ludwig

from ludwig.api import LudwigModel
import pandas as pd
import numpy as np
from sklearn.utils import resample
from nltk.corpus import stopwords
from sklearn.model_selection import train_test_split as tts
import re

train = pd.read_csv('train.csv')
labels = train.columns[3:]

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

def label_list(x):
    labels = []
    for key in  [y for y in x.keys()][3:]:
        if x[key]==1:
            labels.append('_'.join(key.split(' ')))
    return ' '.join(labels)
train['labels'] = train.apply(lambda x: label_list(x),axis=1)

การแยกข้อมูลในการทดสอบรถไฟ

train, test= tts(train,test_size=0.2)

ลุดวิกมาแล้ว

config = {'input_features':[{'name':'TITLE','type':'text',
                            "preprocessing": {"word_tokenizer": "space"},
                            "encoder": {
                                        "type": "bert",
                                        "trainable": False}},
                            {'name':'ABSTRACT','type':'text',
                            "preprocessing": {"word_tokenizer": "space"},
                            "encoder": {
                                        "type": "bert",          
                                        "trainable": False}}],
          
         'output_features':[{'name':'labels','type':'set','loss':{'type': 'sigmoid_cross_entropy'}}],
         'preprocessing':{'split':{'column':'labels','probabilities':[0.7,0.1,0.2]}},
         'trainer':{'type':'trainer',
                    'epochs':100,
                    'batch_size':32,
                    'checkpoints_per_epoch':2,
                    'early_stopping':5,
                    'learning_rate':0.0005,
                    'optimizer':{'type':'adam'}
                   } 
         }
ludwig_model = LudwigModel(config)
train_stats, _, model_dir = ludwig_model.train(train[['TITLE','ABSTRACT','labels']])

มีหลายสิ่งที่ต้องเข้าใจ

  • ไฟล์กำหนดค่าเป็นหัวใจของกระบวนการทั้งหมดนี้ ดังที่เราได้พูดคุยกันก่อนหน้านี้ ในระบบที่ประกาศ ผู้พัฒนาสามารถจัดเตรียมอินพุตสำหรับส่วนต่างๆ ของไปป์ไลน์ได้ ไฟล์ปรับแต่งนี้เก็บส่วนที่ผู้พัฒนาต้องการตัดสินใจ มีหลายส่วนในไฟล์กำหนดค่านี้ เราจะหารือเรื่องสำคัญบางประการ

input_features: เป็นรายการพจนานุกรมที่แต่ละพจนานุกรมมีข้อมูลเกี่ยวกับ input_feature หนึ่งรายการ เช่น ชื่อ ประเภทข้อมูล การประมวลผลล่วงหน้าที่จำเป็นสำหรับคุณลักษณะดังกล่าว ฯลฯ ในกรณีของเรา จะเป็น 'TITLE' และ 'ABSTRACT' 2 คอลัมน์ . นอกจากนี้เรายังจัดเตรียมวิธีการสำหรับสร้างการฝังคำอีกด้วย

Output_features: คล้ายกับ input_features แต่มีชื่อสำหรับคอลัมน์ output_feature / label สำหรับส่วนนี้ เราสามารถพูดถึงฟังก์ชันการสูญเสียได้เช่นกัน ในกรณีนี้ มันคือคอลัมน์ 'labels' ที่มี loss=’sigmoid_corss_entropy' โปรดสังเกตว่าสำหรับการจำแนกประเภทหลายรายการ เราได้เก็บประเภทข้อมูลเป็น 'set' มันสมเหตุสมผลแล้ว ขวา?

ส่วนการประมวลผลล่วงหน้าช่วยให้เราสามารถปฏิบัติตามขั้นตอนการประมวลผลล่วงหน้าได้

1. สำหรับชุดข้อมูลทั้งหมด (เช่น train-test-split)

2. การเตรียมการล่วงหน้าเฉพาะสำหรับประเภทข้อมูลใดประเภทหนึ่ง (เช่นคุณสมบัติสตริงหรือโฟลตทั้งหมดในชุดข้อมูล)

ดังนั้นหากมีขั้นตอนทั่วไปในการประมวลผลล่วงหน้า ก็สามารถใช้ส่วนนี้ได้ เราใช้มันเพื่อแยกภายในระหว่างการฝึก การตรวจสอบ และชุดข้อมูลทดสอบโดยใช้กลยุทธ์แบบสุ่ม

ผู้ฝึกสอน ถูกใช้เพื่อระบุพารามิเตอร์ที่เกี่ยวข้องกับการฝึกโครงข่ายประสาทเทียมที่จะเกิดขึ้นตามจำนวนยุค, ขนาดแบตช์, เครื่องมือเพิ่มประสิทธิภาพ ฯลฯ

ลุดวิกสามารถใช้ระหว่างโมเดล 'ecd' และ 'gbm' โดยใช้พารามิเตอร์ model_type ในการกำหนดค่าโดยที่ค่าเริ่มต้นคือ 'ecd'

'gbm' ไม่มีอะไรนอกจาก Tree boosting algos (เช่น Light GBM)

แต่ 'ECD' (Encoder-Combiner-Decoder) คืออะไร?

มันเป็นสถาปัตยกรรมเครือข่ายประสาทขั้นพื้นฐานที่ลุดวิกดังต่อไปนี้

การออกแบบจึงเรียบง่าย

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

ด้านล่างนี้คุณสามารถดูวิธีการปรับแต่งสถาปัตยกรรมโดยขึ้นอยู่กับคำชี้แจงปัญหาต่างๆ

แม้ว่าจะมีพารามิเตอร์เพิ่มเติมอีกสองสามตัวในไฟล์กำหนดค่าซึ่งคุณสามารถอ่านได้ใน เอกสารประกอบ

สุดท้ายนี้ เรามาสร้างผลลัพธ์สำหรับชุดข้อมูลทดสอบกันดีกว่า

predictions, output_directory = model.predict(test[['TITLE','ABSTRACT']])

'การคาดการณ์' เป็น dataframe ที่มีค่าต่อไปนี้

ตอนนี้ เราจะคำนวณความแม่นยำของมาโคร การเรียกคืน และคะแนน f1 เพื่อวิเคราะห์ประสิทธิภาพของลุดวิก

#basic preprocessing required 

test['predictions'] = [x for x in predictions['labels_predictions'].values]
test['labels'] = test['labels'].transform(lambda x:x.split(' '))

#initializing an empy dataframe
predict = pd.DataFrame(index=[x for x in test.index],columns=['TP','FP','FN']).fillna(0)

การคำนวณ FP, FN และ TP ควบคู่ไปกับการตีและพลาดแบบคลาส

for index,rows in test.iterrows():
    labels_ = set(rows['labels'])
    predict_ = set(rows['predictions'])
    predict.at[index,'TP'] = len(labels_.intersection(predict_))
    predict.at[index,'FP'] = len(predict_-labels_)
    predict.at[index,'FN'] = len(labels_-predict_)

sum_dict = predict.sum()
precision = sum_dict['TP']/(sum_dict['FP']+sum_dict['TP'])
recall = sum_dict['TP']/(sum_dict['FN']+sum_dict['TP'])
f1 = 2*precision*recall/(precision+recall)
print("precision=",precision)
print("recall=",recall)
print("f1=",f1)

ผลลัพธ์ค่อนข้างดีเพราะเราแทบไม่ได้ทำอะไรเลย !!

นั่นคือห่อ ลองใช้ปัญหาการสร้างแบบจำลองอื่นๆ กับลุดวิกแล้วดูว่าลุดวิกเก่งแค่ไหน นอกจากนี้ เอกสารประกอบก็ค่อนข้างจะแย่มาก ดังนั้นหากคุณวางแผนที่จะลองใช้ Ludwig เพียงตรงไปที่ เอกสารประกอบ