ด้วยรหัสใน 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
- นำเข้าไลบรารีที่จำเป็นและโหลดชุดข้อมูล
#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 เพียงตรงไปที่ เอกสารประกอบ