เรียนรู้จากความผิดพลาดของเรา 📈

Python, scikit-learn, Logistic Regression และ Looker มารวมกันเพื่อช่วยผู้จัดการฝ่ายขายของเราค้นหา 'เข็มในกองหญ้า' ได้อย่างไร

นี่เป็นบทความสั้นที่มุ่งเป้าไปที่นักวิเคราะห์การขายและผู้ปฏิบัติงานที่อาจต้องการสำรวจศักยภาพการใช้งาน ML ในขั้นตอนการทำงานของตน มีข้อมูลโค้ด ตัวอย่าง และบทเรียนที่ฉันได้เรียนรู้จากการฝังโมเดลการจัดหมวดหมู่ในกระบวนการขายของเราที่นี่ Qubit

บริบท

ที่ Qubit เราใช้ Salesforce เป็นเครื่องมือ CRM หลักของเรา และในช่วงหลายปีที่ผ่านมา ช่องที่กำหนดเองและขั้นตอนการทำงานเบื้องหลังมากมายได้ถูกสร้างขึ้นเพื่อรวบรวมบริบทเกี่ยวกับโอกาสในการขายให้ได้มากที่สุด

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

ปมของมัน

เราสามารถสร้างโมเดล ML ที่ได้รับการดูแลเพื่อรวบรวมมูลค่าจากข้อมูลการขายในอดีตของเราได้หรือไม่

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

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

(บทความนี้จะไม่ครอบคลุมความกว้างและความเข้าใจของ ML มีบทความที่เขียนดีกว่ามากมายสำหรับเรื่องนั้น ฉันถือว่าคุณมี Python 3 ติดตั้งไว้ล่วงหน้าแล้วในบางพื้นที่)

ฉันควรใช้อัลกอริธึมใด

สำหรับความท้าทายประเภทนี้ จากประสบการณ์และความเข้าใจของฉัน เป็นเรื่องปกติที่จะเริ่มสำรวจประสิทธิภาพของผลิตภัณฑ์ขั้นต่ำ (MVP) ในบริบทนี้ การใช้อัลกอริธึมที่ได้รับการอ้างอิงอย่างดีโดยไม่มีคุณสมบัติทางวิศวกรรมหรือการประมวลผลข้อมูลล่วงหน้าเพียงเล็กน้อยหรือไม่มีเลย เพื่อทำความเข้าใจว่า 'พื้น' อยู่ที่ไหนในส่วนที่เกี่ยวกับความแม่นยำและความแม่นยำของแบบจำลอง MVP ของฉันเกี่ยวข้องกับ Logistic Regression, Decision Tree และอัลกอริธึม Random Forest เนื่องจากตัวแปรเป้าหมายเป็นไบนารี เพื่อให้บทความนี้เน้นย้ำ เราจึงเลือก Binary Logistic Regression และนี่คือแหล่งข้อมูลสำคัญบางส่วนที่ช่วยได้อย่างแน่นอน:

หนังสือ

แหล่งข้อมูลออนไลน์

บทความขนาดกลาง

สมาคมการวิเคราะห์

  • ที่ Qubit เรามีสมาคม Analytics ภายในซึ่งมีสภาพแวดล้อมที่เปิดกว้างและตรงไปตรงมาเพื่อรายงานกลับเกี่ยวกับการพัฒนาโมเดลเพื่อขอความคิดเห็น (ขอเชิญชวนผู้ที่เกี่ยวข้องทุกคน 👊🏻)

ฉันมีอะไรและทำไมสำหรับวิธีการ...

Qubit นำ Looker มาใช้สำหรับ BI ภายใน ในปี 2560 ซึ่งทำให้ฉันสามารถรวม API ของ Looker และคลังข้อมูลของ Qubit ไว้ใน Jupyter Notebooks ได้ เพื่อเปิดการเข้าถึงหนึ่งในไลบรารีการเรียนรู้ของเครื่องของ Python — scikit-learn

สมมติฐานที่ถือโดยทั่วไปคือ:

“… 'ขนาดของข้อตกลงในอดีตที่เราถือไว้นั้นเล็กเกินไป' และ 'ความสอดคล้องของบางสาขา' นั้นอ่อนแอเกินไปที่จะสร้างสิ่งที่สามารถทำได้”

เพื่อจัดการกับสิ่งที่กล่าวมาข้างต้นและเปิดเผยว่าอัลกอริทึม ML ที่ได้รับการดูแลสามารถรวบรวมคุณค่าได้หรือไม่ ฉันได้ดำเนินการตามขั้นตอนต่อไปนี้:

  1. การประมวลผลข้อมูลล่วงหน้า: การโหลดข้อมูล คุณสมบัติการปรับขนาด การใส่ข้อมูล และคุณสมบัติหมวดหมู่การเข้ารหัสด่วนหนึ่งรายการ
  2. ฝึก + ทดสอบ:แยกข้อมูลการฝึก โหลดอัลกอริทึม Logistic Regression ของ scikit-learn การตั้งค่าไฮเปอร์พารามิเตอร์ และบันทึกโมเดลลงดิสก์
  3. ประสิทธิภาพ:การเรียนรู้ การตรวจสอบ และเส้นโค้ง ROC เพื่อเปรียบเทียบกับเมทริกซ์ความสับสน
  4. แชร์:เผยแพร่โมเดลเอาท์พุตทั่วทั้ง Looker

บทความนี้ไม่ได้ครอบคลุมกระบวนการทั้งหมดอย่างแน่นอน ซึ่งมี/กำลังถูกทำซ้ำเพื่อแก้ไขโมเดลเพิ่มเติม!

ความคุ้มครองโอกาส

ก่อนที่จะมีการถกเถียงกันเรื่องข้อมูล ฉันร่างแนวคิดโดยใช้จุดข้อมูลที่ฉันรู้ว่าเรามีโอกาสในการขายโดยรอบ หลังจากทำซ้ำหลายครั้ง นี่คือรายการที่ฉันดำเนินการ:

  • ความเร็วของโอกาส:ในแง่ของอายุและเวลาที่ใช้ในขั้นตอนการขายสำหรับโอกาสทางการขาย
  • การมีส่วนร่วมของตัวแทนขาย:ในแง่ของการเปลี่ยนแปลงในฟิลด์โอกาสสำคัญ เช่น 'วันที่ปิด' และระยะทางสุทธิที่เดินทาง (ผ่านไปป์การขาย)
  • การมีส่วนร่วมของ HubSpot:เราใช้ HubSpot เป็นเครื่องมือทางการตลาด ซึ่งมีคะแนนเชิงประจักษ์ที่เราสามารถรวบรวมและผสานเข้ากับโอกาสได้
  • ตำแหน่งของข้อตกลง:ตำแหน่งทางภูมิศาสตร์ของข้อตกลงและตัวแทนทั้งคู่มีอัตราการชนะในอดีตที่สามารถให้บริบทได้
  • ขนาดข้อตกลง:นี่อาจเป็นคุณลักษณะที่มีประโยชน์ ขึ้นอยู่กับประเภทธุรกิจ SaaS ที่คุณเป็นและกลยุทธ์ในการเข้าสู่ตลาดของคุณ
  • ประเภทของโอกาส: พวกเราที่ Qubit จำหน่ายผลิตภัณฑ์หลายประเภท โดยได้รับการออกแบบโดยคำนึงถึงวงจรการขายที่แตกต่างกัน
  • บริบทการขาย:ที่ Qubit เรามีบริบทมากมายภายในกรอบงานการขาย เช่น MEDDPICC ซึ่งพิสูจน์แล้วว่าเป็นคุณสมบัติที่ดี

รายการนี้เสริมด้วยการสนทนาจากทั่วทั้งธุรกิจและการวิเคราะห์เฉพาะกิจเพื่อยืนยันความสำคัญของฟีเจอร์ มีการตรวจสอบอย่างต่อเนื่อง แต่เป็นจุดเริ่มต้นสำหรับการพัฒนาแบบจำลอง

1. การประมวลผลข้อมูลล่วงหน้า

ส่วนนี้จะกล่าวถึงวิธีที่ฉันใช้ Looker's API, ฟังก์ชัน Pandas 'pandas.read_sql_query' และ SQLAlchemy เพื่อปรับปรุงกระบวนการ

โหลดไลบรารี่

โหลดข้อมูล

ด้วยฟังก์ชันด้านล่างนี้ ฉันจึงสามารถนำเข้าข้อมูลล่าสุดจาก Looker หรือจาก MySQL Views ได้ภายในไม่กี่บรรทัด

'query_id' สามารถพบได้ในแท็บ "แบบสอบถาม" ภายในแผงการดูแลระบบของ Looker ("เอกสาร Looker")

ฟังก์ชันข้างต้นมีประโยชน์สำหรับการโหลดตารางที่รวมไว้ล่วงหน้าซึ่งอาจมีช่องจากการคำนวณในโค้ดที่สั้นกว่าและสะอาดกว่า

หมายเหตุ ซึ่งเป็นคุณลักษณะใหม่ของ Looker 'merge results' ยังใช้งานไม่ได้กับ API และตัวอย่าง 'query_id's นั้นเกี่ยวข้องกับอินสแตนซ์ของเราเท่านั้น

# Looker API
age_from_creation = get_data('147670')
deal_size = get_data('138578')
hubspot = get_data('146956')
# Data Warehouse
sql = "select * from pipe_qualifier_data"
days_in_stage_df = pd.read_sql_query(sql, data_warehouse)

การใส่ร้ายและการจัดหมวดหมู่

Logistic Regression ไม่สามารถจัดการ NaN ได้ ดังนั้นจึงจำเป็นต้องใส่กรอบข้อมูลทั้งหมด นอกเหนือจากการใส่คุณสมบัติต่างๆ แล้ว ยังจำเป็นต้องมี 'การเข้ารหัสแบบ hot encoding' ของคุณสมบัติบางอย่างอีกด้วย ด้านล่างนี้เป็นตัวอย่างบางส่วนที่ฉันใช้:

# Impute NaNs caused by merging (categorically and continuously)
df.feature_X.fillna(value="Unknown", inplace=True)
df.feature_Y.fillna(value=0, inplace=True)
# Impute Negative Continious Variables
df.loc[df['days_at_0'] < 0, 'days_at_0'] = 0
df.loc[df['days_at_1'] < 0, 'days_at_1'] = 0
df.loc[df['days_at_2'] < 0, 'days_at_2'] = 0
# String Search Categorisation
def check_opp_name(oppname):
    if 'xxx' in oppname.lower():
        answer = 'x_opp'
    elif 'xxc' in oppname.lower():
        answer = 'x_opp'
    elif 'y' in oppname.lower():
        answer = 'y_opp'
    else:
        answer = 'non_xy_opp'
    return answer
df['opp_definition'] = df.opportunity_name.apply(check_opp_name)
# Create dummy variables (one hot encoding)
df = pd.get_dummies(df)
# Assign target variable and drop unwanted columns
df['target_variable'] = df['contract_stage']
df.drop(
    [
        'contract_stage_Contract_Signed', 'contract_stage_Lost',
        'key_deal_0'
    ],
    axis=1,
    inplace=True)
# Df tidy up
df.columns = map(str.lower, df.columns)
df = df.rename(
    index=str,
    columns={
        "meddpicc": "meddpicc_populated",
        "key_deal": "key_deal"
    })

ความท้าทายด้านข้อมูล

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

# SNS pair plot
g = sns.pairplot(
    df[[
        "age_of_opp", "close_date_movements", 
        "days_at_0", "pipe_exp",
        "sum_of_close_date_moves", "days_at_1", 
        "max_hubspot_score", "target_variable"
    ]],
    hue="target_variable",
    diag_kind="hist")
for ax in g.axes.flat:
    plt.setp(ax.get_xticklabels(), rotation=45)

ความท้าทายคือสถานการณ์ 'เข็มในกองหญ้า' แบบคลาสสิก ซึ่งชุดข้อมูลการฝึกอบรมไม่สมดุลอย่างมาก โดยคลาสเป้าหมายมีมูลค่า ‹10% ของทั้งหมด สิ่งนี้ประกอบกับความจริงที่ว่า .shape ของกรอบข้อมูลส่งคืนเฉพาะ 2010 แถว

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

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

2. การฝึกอบรมโมเดล + การทดสอบ

อินพุตได้รับมาตรฐานโดยใช้ฟังก์ชัน scale() ของ sklearn ซึ่งได้รับการปรับปรุงประสิทธิภาพบางส่วน เนื่องจากค่าผิดปกติมีผลกระทบอย่างมากต่อการถดถอยของลอจิสติก การพิจารณาในอนาคตคือการใช้ 'RobustScalar()' เนื่องจากใช้ช่วงระหว่างควอไทล์เพื่อขจัดอิทธิพลของค่าผิดปกติได้ดีขึ้น

เมื่อพิจารณาจากขนาดตัวอย่างที่เล็ก จึงมีการเลือกการแยกรถไฟ 70/30 กับการทดสอบ ซึ่งตามหลักการแล้ว ควรจะเป็น 60/40 เพื่อทดสอบความสามารถของแบบจำลองในการสรุปเพิ่มเติม การพิจารณาในอนาคตคือการสำรวจการใช้ 'StratifiedKFold()' และการตรวจสอบข้ามเพื่อเพิ่มขนาดชุดการทดสอบ/การฝึกอบรม และรักษาความสมดุลของชั้นเรียน

# Splitting df into target and features
X = df[df.loc[:, df.columns != 'target_variable'].columns]
y = df['target_variable']
# Splitting features into a 70/30 train/test ratio
X_train, X_test, y_train, y_test = train_test_split(X, 
                                                    y, 
                                                    test_size=0.3)
# Scale inputs
X_train_scale = scale(X_train)
X_test_scale = scale(X_test)
# Logistic Regression C Value
logreg_scaled = LogisticRegression(C=1.0)
logreg_scaled.fit(X_train_scale, y_train)

ฟังก์ชัน LogisticRegression ของ Scikit-Learn มีพารามิเตอร์ 'class_weight=' ซึ่งสามารถใช้การถ่วงน้ำหนักโดยอัตโนมัติตามสัดส่วนผกผันกับความถี่ของชั้นเรียน

# Logistic Regression Class Weighting
logreg_scaled_balanced = LogisticRegression(C=1.0,                 
                                            class_weight='balanced')
logreg_scaled_balanced.fit(X_train_scale, y_train)

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

ฟังก์ชันด้านล่างนี้มีประโยชน์มากสำหรับการแสดงเส้นโค้งการตรวจสอบและการเรียนรู้ของแบบจำลอง Logistic Regression ของฉันอย่างชัดเจนในระหว่างการฝึกอบรมและการทดสอบ

“เส้นโค้งการเรียนรู้” เป็นวิธีที่ดีในการทำความเข้าใจว่า 'การเรียนรู้' (แกน y) เปลี่ยนแปลงไปอย่างไรเมื่อมี 'ประสบการณ์' (แกน x) มากขึ้น กราฟแสดงตามคุณลักษณะปัจจุบัน จำนวนตัวอย่างการฝึกอบรมดูเหมือนว่าจะเพียงพอสำหรับการลู่เข้า

ค่า C 0.1 และ 1.0 ถูกนำมาใช้เพื่อเปรียบเทียบประสิทธิภาพและสมดุลความเสี่ยงของการติดตั้งมากเกินไป — C=1.0 ถูกใช้ในการกำหนดค่าโมเดลขั้นสุดท้าย

อีกวิธีหนึ่งอาจเป็นการใช้ฟังก์ชัน `GridSearchCV` ของ scikit-learn ร่วมกับการตรวจสอบข้ามเพื่อยืนยันค่าไฮเปอร์พารามิเตอร์ที่ดีที่สุดอย่างละเอียดถี่ถ้วน

C : ลอย ค่าเริ่มต้น: 1.0

ค่าผกผันของความแข็งแกร่งในการทำให้เป็นมาตรฐาน จะต้องเป็นทศนิยมเชิงบวก เช่นเดียวกับในเครื่องเวกเตอร์ที่รองรับ ค่าที่น้อยกว่าจะระบุถึงการทำให้เป็นมาตรฐานที่แข็งแกร่งยิ่งขึ้น

การถดถอยโลจิสติก — Scikit-เรียนรู้

("แหล่งที่มา")

การใช้ไลบรารีดองของ Python ทำให้สามารถ 'ทำให้แบน' หรือ 'ซีเรียลไลซ์' โมเดลและการกำหนดค่าปัจจุบันเป็นไฟล์ .sav ได้อย่างรวดเร็วและง่ายดาย

โมดูล pickle ใช้อัลกอริธึมพื้นฐาน แต่ทรงพลังสำหรับซีเรียลไลซ์และดีซีเรียลไลซ์โครงสร้างอ็อบเจ็กต์ Python “Pickling” เป็นกระบวนการที่ลำดับชั้นของอ็อบเจ็กต์ Python จะถูกแปลงเป็นไบต์สตรีม และ “unpickling” เป็นการดำเนินการผกผัน โดยที่ไบต์สตรีมจะถูกแปลงกลับเป็นลำดับชั้นของอ็อบเจ็กต์

# To Save
filename = 'pipe_qualifier_model.sav'
pickle.dump(logreg_scaled, open(filename, 'wb'))
# To Open
logreg_scaled = pickle.load(open('pipe_qualifier_model.sav', 'rb'))

การบันทึกในเครื่องลงดิสก์มีประโยชน์สำหรับการผลิตการใช้โมเดล โดยไม่จำเป็นต้องโหลดซ้ำ ฝึก และทดสอบโมเดลอย่างต่อเนื่อง

3. ประสิทธิภาพ

เส้นโค้งลักษณะการทำงานของตัวรับ (“ROC”) หรือพื้นที่ใต้เส้นโค้ง (“AUCROC”) มักใช้เพื่อประเมินประสิทธิภาพของเกณฑ์การจำแนกประเภทโมเดลการเรียนรู้ของเครื่อง มักจะเปรียบเทียบกับลักษณนามการเดาแบบสุ่ม โดยแสดงเป็นเส้นตรงผ่าน (0,0) และ (1,1)

logit_roc_auc = roc_auc_score(y_test,
                              logreg_scaled.predict(X_test_scale))
fpr, tpr, thresholds = roc_curve(y_test,
                       logreg_scaled.predict_proba(X_test_scale)             
                       [:,1])
plt.figure()
plt.plot(fpr, tpr, label = 'Logistic Regression Scaled (area = %0.2f)' % logit_roc_auc)
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve (scaled)')
plt.legend(loc="lower right")
plt.show()

ด้วยคำจำกัดความของเส้นโค้ง ROC พวกมันสัมพันธ์กับเมทริกซ์ที่สับสน การพิจารณาในอนาคตคือการลดเกณฑ์การจำแนกแบบจำลองเพื่อให้มีอิทธิพลต่อการมองโลกในแง่ดีโดยพิจารณาจากการใช้งานจริง

เส้นโค้ง ROC ถูกสร้างขึ้นโดยการวางแผนอัตราบวกที่แท้จริง (TPR) เทียบกับอัตราบวกลวง (FPR) ที่การตั้งค่าเกณฑ์ต่างๆ — วิกิพีเดีย

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

ตามที่คาดไว้ เนื่องจากความไม่สมดุลภายในข้อมูล โมเดลจึงได้คะแนนสูงในด้านความแม่นยำและการเรียกคืนของคลาสที่ไม่ใช่เป้าหมาย (ข้อตกลงการสูญเสีย) เนื่องจากเป็นประชากรส่วนใหญ่

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

# Confusion Matrix
y_pred = logreg_scaled.predict(X_test_scale)
print(classification_report(y_test, y_pred))

ในแง่ของคนธรรมดา:

ความแม่นยำ:

  • 97% ของข้อตกลงที่คาดการณ์ว่าจะแพ้นั้นสูญหายไป
  • 80% ของข้อตกลงที่คาดว่าจะชนะได้รับชัยชนะ

เรียกคืน:

  • 99% ของข้อตกลงที่สูญเสียไปภายในข้อมูลได้รับการจัดประเภทอย่างถูกต้อง
  • 50% ของข้อตกลงที่ชนะภายในข้อมูลได้รับการจัดประเภทอย่างถูกต้อง

สังเกตคอลัมน์ 'แนวรับ' ที่ต่ำ ซึ่งระบุขนาดของชุดทดสอบ

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

ในทางปฏิบัติ เรากำลังสังเกตเห็นระดับความแม่นยำที่ใกล้เคียงกัน (คะแนน F1 = 62%) เนื่องจากเราใช้โมเดลนี้ในช่วง "ไม่ต่อเนื่อง" เมื่อสิ้นสุดไตรมาสการขาย ความคิดเห็นนี้มีประโยชน์อย่างยิ่งสำหรับการเลือกคุณสมบัติใหม่เพื่อรวบรวมบริบทที่เราอาจขาดหายไปในปัจจุบัน

4. แบ่งปัน

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

“บทเรียนที่เรียนมามีคุณค่าอะไรบ้าง?”

วิธีที่มีประสิทธิภาพมากที่สุดในการแจกจ่ายการเรียนรู้ใหม่ๆ คือในรูปแบบของความสำคัญของคุณลักษณะ ฉันใช้สองเทคนิคเพื่อเน้นคุณลักษณะที่มีอิทธิพล:

ค่าสัมประสิทธิ์แบบจำลอง Logit

# loop through columns and append the corresponding coefficient
w_con = []
for idx, col_name in enumerate(X_train.columns):    
    w_con.append([col_name, logreg_scaled.coef_[0][idx]])
print("Model Logit Coefficients")
# Return the real and absolute values for sorting
df = pd.DataFrame(w_con)
df["abs_coeffs"] = abs(df[1])
df.sort_values(by=["abs_coeffs"], ascending=False, inplace=True)
df = df.rename(index=str, columns={0: "Feature", 1: "Coefficient"})
df.head(10)

# Load up Random Forest
rf = RandomForestClassifier()
rf.fit(X_train_scale, y_train)
importances = rf.feature_importances_
# Sort by importance
std = np.std([tree.feature_importances_ for tree in rf.estimators_],
             axis=0)
indices = np.argsort(importances)[::-1]
feature_importances = pd.DataFrame(
    rf.feature_importances_, index=X_train.columns,
    columns=['importance']).sort_values(
        'importance', ascending=False)
print("Random Forest Classifier: Feature Importance")
feature_importances.head(10)

การใช้ไม่เพียงแต่ขนาดของการถ่วงน้ำหนักแต่รวมถึงทิศทาง ฉันจึงสามารถแปลงการถ่วงน้ำหนักภายในเป็นการสรุปตามบริบทได้

นี่คือเรื่องย่อ:

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

นอกเหนือจากที่กล่าวมาข้างต้น ฉันตัดสินใจส่งผลลัพธ์กลับเข้าไปใน Looker เพื่อเผยแพร่ไปยังกลุ่มผู้ใช้บางกลุ่ม สิ่งนี้ทำให้ฉันสามารถนำเสนอข้อมูลควบคู่ไปกับบริบทการขายที่กว้างขึ้นได้ โดยทำส่วนสุดท้ายของเวิร์กโฟลว์การพัฒนาโมเดลให้เสร็จสิ้น

กิน นอน คลั่งไคล้ ทำซ้ำ

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

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

คิดว่าโปรเจ็กต์นี้เป็นภารกิจสอดแนม ซึ่งภายในมีการค้นพบคุณค่าระดับผิวเผิน แต่ยังมีศักยภาพที่จะทำมากกว่านี้ การใช้กฎ 80/20 ฉันจะตัดสินว่าผลตอบแทนจากการลงทุนก่อนกำหนด (เวลา) จำนวนมากได้รับการยอมรับแล้ว โดยมีบางอย่างที่ยากกว่าที่จะเข้าถึงรางวัลได้ก่อนที่ผลตอบแทนที่ลดลงจะมีผล

โปรดติดตามอ่านเรื่องสั้นอื่นๆ เกี่ยวกับงาน BI ที่เรากำลังทำอยู่ที่ Qubit!

🚀