編者按:Sapient數(shù)據(jù)科學(xué)家Deepak Jhanji通過實(shí)例演示了基于Python進(jìn)行機(jī)器學(xué)習(xí)的流程:探索性數(shù)據(jù)分析、特征工程、訓(xùn)練模型、評(píng)估結(jié)果.
機(jī)器學(xué)習(xí)提供了一個(gè)無需明確編程、可以自行學(xué)習(xí)和提升的系統(tǒng)。它使用特定的處理數(shù)據(jù)的算法自行學(xué)習(xí)。在這篇教程中,我們將使用Python和XGBoost預(yù)測簽證結(jié)果。
這篇教程主要介紹以下內(nèi)容:
探索性數(shù)據(jù)分析
特征工程和特征提取
基于XGBoost算法訓(xùn)練數(shù)據(jù)集
使用訓(xùn)練好的模型進(jìn)行預(yù)測
加載庫
Python庫是函數(shù)和方法的匯集,讓你在無需自行實(shí)現(xiàn)算法的情況下編寫代碼。相應(yīng)地,你需要下載、安裝、引入所用的庫。
NumPy,簡稱np,是Python的基礎(chǔ)性的科學(xué)計(jì)算包。它包括強(qiáng)大的N維數(shù)組對(duì)象,精密的函數(shù),集成C/C++的工具,線性代數(shù),隨機(jī)數(shù)。緊隨其后的是pandas,簡稱pd,一個(gè)開源的BSD許可庫,提供高性能、易于使用的數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)分析工具。接著是scikit learn/sklean庫,提供機(jī)器學(xué)習(xí)算法。除了這些基礎(chǔ)性的庫之外,這篇教程還用到了Statistics(提供mode()等統(tǒng)計(jì)函數(shù))、re(正則表達(dá)式)、XGboost(XGBoost分類器)。
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model importLogisticRegression
from sklearn.metrics import confusion_matrix, classification_report
from statistics import mode
import re
from xgboost importXGBClassifier
H1B簽證和數(shù)據(jù)集
數(shù)據(jù)集可以通過Kaggle獲?。簄sharan/h-1b-visa
它包括五年的H-1B申請(qǐng)記錄,共計(jì)近三百萬條記錄。數(shù)據(jù)集的列包括狀態(tài)、雇主名稱、工作地點(diǎn)、職位、現(xiàn)行工資、職業(yè)代碼、年份。
數(shù)據(jù)來自外國勞工認(rèn)證辦公室(OFLC),每年都把可公開披露的數(shù)據(jù)上傳至網(wǎng)絡(luò)。H1B簽證是一種需求強(qiáng)烈的非移民簽證,允許專門職業(yè)的外國勞工進(jìn)入國境。H-1B簽證是一種基于雇傭關(guān)系的非移民簽證,對(duì)美國的臨時(shí)外國勞工發(fā)放。外國人想要申請(qǐng)H1-B簽證,必須有美國雇主為其提供工作,并向美國移民局提交H-1B申請(qǐng)。這也是國際留學(xué)生完成學(xué)業(yè)開始全職工作后最常見的簽證申請(qǐng)類別。
H1B申請(qǐng)流程的第一步是美國雇主為外國勞工提交H1B申請(qǐng)。第二步是由州就業(yè)保障機(jī)構(gòu)確認(rèn)現(xiàn)行工資和實(shí)際工資。如果現(xiàn)行工資高于潛在雇主提供的工資,那么需要進(jìn)行工資標(biāo)準(zhǔn)審批。H1B申請(qǐng)流程的第三步是提交勞工條件申請(qǐng)。接下來的步驟是提交H1B申請(qǐng)至USCIS(美國公民及移民服務(wù)局)的相應(yīng)辦公室。各地的H1B申請(qǐng)?zhí)幚頃r(shí)間不同。如果你希望加快申請(qǐng),可以選擇加急處理。H1B申請(qǐng)流程的最后一步是通過輸入收據(jù)號(hào)查詢H1B簽證狀態(tài)。一旦USCIS記錄了你的申請(qǐng),就會(huì)在他們的系統(tǒng)中更新你的簽證狀態(tài)。
數(shù)據(jù)集中,每個(gè)樣本應(yīng)該包含以下信息:
CASE_ID每個(gè)申請(qǐng)唯一的編號(hào)
CASE_STATUS申請(qǐng)狀態(tài),這是目標(biāo)變量。
EMPLOYER_NAME提交申請(qǐng)的雇主名稱。
SOC_NAME職業(yè)名稱。
JOB_Title頭銜。
FULL_TIME_POSITION是否是全職職位。
PREVAILING_WAGE職位的現(xiàn)行工資為支付給類似勞工的平均工資。
YEAR提交h1b申請(qǐng)的年份。
WORKSITE工作地點(diǎn)所在州、城市。
Lon工作地點(diǎn)經(jīng)度。
Lat工作地點(diǎn)緯度。
加載數(shù)據(jù)集
首先要做的是將數(shù)據(jù)集加載為對(duì)象。pandas的.read_csv()方法可以加載csv文件:
df = pd.read_csv('C:/Users/djhanj/Downloads/h1b_TRAIN.csv')
理解數(shù)據(jù)
加載數(shù)據(jù)后,總是建議探索數(shù)據(jù)集,以確保加載的數(shù)據(jù)結(jié)構(gòu)、格式正確,所有變量或特征正確加載。
.info()方法可以用來檢查數(shù)據(jù)信息。在我們的例子上,這個(gè)方法顯示數(shù)據(jù)以DataFrame的格式存儲(chǔ),其中1個(gè)變量為整數(shù)格式,4個(gè)變量為浮點(diǎn)數(shù)格式,6個(gè)變量為對(duì)象格式。
.head()方法返回首5行數(shù)據(jù)。這能讓你大概了解數(shù)據(jù)集。
.describe()方法將顯示最小值、最大值、均值、中位數(shù)、標(biāo)準(zhǔn)差,以及所有整數(shù)和浮點(diǎn)數(shù)變量的數(shù)目。
df.info()
df.head()
df.describe()
RangeIndex: 2251844 entries, 0 to 2251843
Data columns (total 11 columns):
CASE_ID int64
CASE_STATUS object
EMPLOYER_NAME object
SOC_NAME object
JOB_TITLE object
FULL_TIME_POSITION object
PREVAILING_WAGE float64
YEAR float64
WORKSITE object
lon float64
lat float64
dtypes: float64(4), int64(1), object(6)
memory usage: 189.0+ MB
數(shù)據(jù)集共有11列,其中1列是目標(biāo)變量(case_status)。也就是說,數(shù)據(jù)有1個(gè)目標(biāo)變量和10個(gè)獨(dú)立變量。你當(dāng)然應(yīng)該檢查下目標(biāo)變量的分類。你可以在df的case_status特征上使用.unique()方法。
這是一個(gè)分類問題。你需要預(yù)測case_status的所屬分類。
df['CASE_STATUS'].unique()
df.head(10)
特征工程和數(shù)據(jù)預(yù)處理
注意,目標(biāo)變量包含6個(gè)不同的分類:
Certified
Certified Withdrawn
Rejected
Invalidatd
Pending Quality and compliance review
Denied
取決于具體的業(yè)務(wù)問題,你需要決定這是一個(gè)多元分類問題,還是一個(gè)二元分類問題。如果是二元分類問題,那么只有Certified(批準(zhǔn))和Denied(拒簽)兩個(gè)分類。所以你要做的第一件事是將剩余的分類轉(zhuǎn)換為Certified或Denied。其中,Rejected和Invalidated都是拒簽的情形,所以應(yīng)該將這兩種狀態(tài)轉(zhuǎn)換為Denied。在美簽中,Pending Quality and compliance的最終結(jié)果最可能是拒簽,所以也應(yīng)該轉(zhuǎn)換為Denied。Certified withdrawn(批準(zhǔn)后撤回)則是批準(zhǔn)的情形,因?yàn)楹炞C已經(jīng)批準(zhǔn)了,只不過雇主因?yàn)榉N種原因(比如勞工更換工作單位)而決定撤回申請(qǐng)。
df.CASE_STATUS[df['CASE_STATUS']=='REJECTED'] = 'DENIED'
df.CASE_STATUS[df['CASE_STATUS']=='INVALIDATED'] = 'DENIED'
df.CASE_STATUS[df['CASE_STATUS']=='PENDING QUALITY AND COMPLIANCE REVIEW - UNASSIGNED'] = 'DENIED'
df.CASE_STATUS[df['CASE_STATUS']=='CERTIFIED-WITHDRAWN'] = 'CERTIFIED'
至于Withdrawn(撤回)分類,由于很難預(yù)測數(shù)據(jù)集中的Withdrawn案例最終結(jié)果如何,我們可以直接移除這一分類。另一個(gè)移除Withdrawn分類的原因是它在整個(gè)數(shù)據(jù)集中所占的比例小于1%,這意味著模型很可能無法精確分類Withdrawn分類。
df = df.drop(df[df.CASE_STATUS == 'WITHDRAWN'].index)
查看下數(shù)據(jù)集中批準(zhǔn)和拒簽的比例各是多少?
df = df[df['CASE_STATUS'].notnull()]
print(df['CASE_STATUS'].value_counts())
結(jié)果:
CERTIFIED 2114025
DENIED 70606
Name: CASE_STATUS, dtype: int64
整個(gè)數(shù)據(jù)集中,只有大約3.2%的申請(qǐng)被拒,這意味著,數(shù)據(jù)集中大約96.8%的申請(qǐng)被批準(zhǔn)了。這表明數(shù)據(jù)集是高度失衡的。失衡數(shù)據(jù)集的一大問題是模型將更偏向頻繁出現(xiàn)的分類;在這個(gè)例子中,模型將偏向批準(zhǔn)。有一些解決失衡問題的技術(shù),不過本教程沒有使用它們。
處理缺失值
這個(gè)數(shù)據(jù)集并不整潔,其中包含很多缺失值。你必須處理缺失值。最簡單的方法是移除它們,不過這會(huì)損失信息。讓我們逐步看看如何處理缺失值:
CASE_ID 0
CASE_STATUS 0
EMPLOYER_NAME 11
SOC_NAME 12725
JOB_TITLE 6
FULL_TIME_POSITION 1
PREVAILING_WAGE 41
YEAR 0
WORKSITE 0
lon 77164
lat 77164
dtype: int64
就EMPLOYER_NAME(雇主名稱)而言,我們可以用眾數(shù)(最常出現(xiàn)的值)填充11項(xiàng)缺失值:
df['EMPLOYER_NAME'] = df['EMPLOYER_NAME'].fillna(df['EMPLOYER_NAME'].mode()[0])
如果不放心,我們可以用assert語句確保不存在空值。如有空值,Python會(huì)拋出AssertionError。
assert pd.notnull(df['EMPLOYER_NAME']).all().all()
下面我們將查看prevailing_wage(現(xiàn)行工資)。大部分申請(qǐng)的工資都在4萬到8萬美元之間。某些申請(qǐng)的工資超過50萬美元,有些則為0美元——由于這些情形很罕見,它們應(yīng)該作為離散值移除(在2%分位和98%分位處截?cái)啵?/p>
df.loc[df.PREVAILING_WAGE < 34029, 'PREVAILING_WAGE']= 34029
df.loc[df['PREVAILING_WAGE'] > 138703, 'PREVAILING_WAGE']= 138703
截?cái)嘀螅F(xiàn)行工資的均值和中位數(shù)非常接近。中位數(shù)為6萬5千美金,而均值為6萬8千美金。我們最終將用均值替換缺失值。不過由于這兩個(gè)值非常接近,你也可以用中位數(shù)替換。
df.PREVAILING_WAGE.fillna(df.PREVAILING_WAGE.mean(), inplace = True)
JOB_TITLE、FULL_TIME_POSITION、SOC_NAME列也可以使用眾數(shù)填充缺失值。
df['JOB_TITLE'] = df['JOB_TITLE'].fillna(df['JOB_TITLE'].mode()[0])
df['FULL_TIME_POSITION'] = df['FULL_TIME_POSITION'].fillna(df['FULL_TIME_POSITION'].mode()[0])
df['SOC_NAME'] = df['SOC_NAME'].fillna(df['SOC_NAME'].mode()[0])
移除lat和lon列
我們將移除lat(緯度)和lon(經(jīng)度)列,因?yàn)樗鼈兒凸ぷ鞯攸c(diǎn)列重復(fù)了。在DataFrame上使用drop方法可以移除列,只需指定列名和軸(0表示行、1表示列)。
df = df.drop('lat', axis = 1)
df = df.drop('lon', axis = 1)
特征創(chuàng)建
基于現(xiàn)有的數(shù)據(jù)有可能制作一個(gè)模型,不過,某些列包含尚待提取的信息。
EMPLOYER_NAME包含雇主的名稱,其中包含大量不同的雇主(為雇員提交申請(qǐng)的公司)。我們無法直接在模型中使用EMPLOYER_NAME,因?yàn)轭悇e太多了;超過500個(gè)不同雇主。
提交申請(qǐng)最多的5家公司是Infosys、TCS、Wipro、Deloitte、IBM。不過,根據(jù)經(jīng)驗(yàn),由大學(xué)提交的申請(qǐng)更容易通過。
所以,問題是,我們?nèi)绾螐脑撎卣髦刑崛〕鲆恍┬畔ⅲ?/p>
好吧,我們大概可以創(chuàng)建一個(gè)名為NEW_EMPLOYER的新特征:雇主名稱是否包含University(大學(xué))字符串。
創(chuàng)建一個(gè)空列相當(dāng)簡單:
df['NEW_EMPLOYER'] = np.nan
在檢查是否包含字符串時(shí),為了避免大小寫問題,我們將雇主名稱統(tǒng)一轉(zhuǎn)換為小寫:
df['EMPLOYER_NAME'] = df['EMPLOYER_NAME'].str.lower()
df.NEW_EMPLOYER[df['EMPLOYER_NAME'].str.contains('university')] = 'university'
df['NEW_EMPLOYER']= df.NEW_EMPLOYER.replace(np.nan, 'non university', regex=True)
變量SOC_NAME也存在這個(gè)問題。它包括職業(yè)名稱。我們將創(chuàng)建一個(gè)名為OCCUPATION的新變量:
df['OCCUPATION'] = np.nan
df['SOC_NAME'] = df['SOC_NAME'].str.lower()
df.OCCUPATION[df['SOC_NAME'].str.contains('computer','programmer')] = 'computer occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('software','web developer')] = 'computer occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('database')] = 'computer occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('math','statistic')] = 'Mathematical Occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('predictive model','stats')] = 'Mathematical Occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('teacher','linguist')] = 'Education Occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('professor','Teach')] = 'Education Occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('school principal')] = 'Education Occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('medical','doctor')] = 'Medical Occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('physician','dentist')] = 'Medical Occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('Health','Physical Therapists')] = 'Medical Occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('surgeon','nurse')] = 'Medical Occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('psychiatr')] = 'Medical Occupations'
df.OCCUPATION[df['SOC_NAME'].str.contains('chemist','physicist')] = 'Advance Sciences'
df.OCCUPATION[df['SOC_NAME'].str.contains('biology','scientist')] = 'Advance Sciences'
df.OCCUPATION[df['SOC_NAME'].str.contains('biologi','clinical research')] = 'Advance Sciences'
df.OCCUPATION[df['SOC_NAME'].str.contains('public relation','manage')] = 'Management Occupation'
df.OCCUPATION[df['SOC_NAME'].str.contains('management','operation')] = 'Management Occupation'
df.OCCUPATION[df['SOC_NAME'].str.contains('chief','plan')] = 'Management Occupation'
df.OCCUPATION[df['SOC_NAME'].str.contains('executive')] = 'Management Occupation'
df.OCCUPATION[df['SOC_NAME'].str.contains('advertis','marketing')] = 'Marketing Occupation'
df.OCCUPATION[df['SOC_NAME'].str.contains('promotion','market research')] = 'Marketing Occupation'
df.OCCUPATION[df['SOC_NAME'].str.contains('business','business analyst')] = 'Business Occupation'
df.OCCUPATION[df['SOC_NAME'].str.contains('business systems analyst')] = 'Business Occupation'
df.OCCUPATION[df['SOC_NAME'].str.contains('accountant','finance')] = 'Financial Occupation'
df.OCCUPATION[df['SOC_NAME'].str.contains('financial')] = 'Financial Occupation'
df.OCCUPATION[df['SOC_NAME'].str.contains('engineer','architect')] = 'Architecture & Engineering'
df.OCCUPATION[df['SOC_NAME'].str.contains('surveyor','carto')] = 'Architecture & Engineering'
df.OCCUPATION[df['SOC_NAME'].str.contains('technician','drafter')] = 'Architecture & Engineering'
df.OCCUPATION[df['SOC_NAME'].str.contains('information security','information tech')] = 'Architecture & Engineering'
df['OCCUPATION']= df.OCCUPATION.replace(np.nan, 'Others', regex=True)
由于所在州對(duì)簽證申請(qǐng)影響重大,我們將從WORKSITE中分割出州信息:
df['state'] = df.WORKSITE.str.split('\s+').str[-1]
為了計(jì)算概率,我們需要將目標(biāo)分類轉(zhuǎn)換為二值,即0和1.
from sklearn import preprocessing
class_mapping = {'CERTIFIED':0, 'DENIED':1}
df["CASE_STATUS"] = df["CASE_STATUS"].map(class_mapping)
移除用不到的變量:
df = df.drop('EMPLOYER_NAME', axis = 1)
df = df.drop('SOC_NAME', axis = 1)
df = df.drop('JOB_TITLE', axis = 1)
df = df.drop('WORKSITE', axis = 1)
df = df.drop('CASE_ID', axis = 1)
在閱讀建模部分之前,別忘了檢查變量的數(shù)據(jù)類型。例如,有些變量應(yīng)該被用作類別或因子,但是它們的格式卻是對(duì)象字符串。
所以,我們需要將這些變量的類型從對(duì)象轉(zhuǎn)為類別,因?yàn)樗鼈儗儆陬悇e特征。
df1[['CASE_STATUS', 'FULL_TIME_POSITION', 'YEAR','NEW_EMPLOYER','OCCUPATION','state']] = df1[['CASE_STATUS', 'FULL_TIME_POSITION', 'YEAR','NEW_EMPLOYER','OCCUPATION','state']].apply(lambda x: x.astype('category'))
切分?jǐn)?shù)據(jù)為訓(xùn)練集和測試集
將數(shù)據(jù)集一分為二,60%為訓(xùn)練集,40%為測試集。
X = df.drop('CASE_STATUS', axis=1)
y = df.CASE_STATUS
seed = 7
test_size = 0.40
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=seed)
檢查一下訓(xùn)練集中是否有null值:
print(X_train.isnull().sum())
應(yīng)該沒有:
FULL_TIME_POSITION 0
PREVAILING_WAGE 0
YEAR 0
NEW_EMPLOYER 0
OCCUPATION 0
state 0
dtype: int64
由于XGBoost只能處理數(shù)值數(shù)據(jù)。因此我們需要使用pd.get_dummies()對(duì)類別值進(jìn)行獨(dú)熱編碼。
X_train_encode = pd.get_dummies(X_train)
X_test_encode = pd.get_dummies(X_test)
XGBoost
XGBoost是“Extreme Gradient Boosting”(極端梯度提升)的簡稱,這是一種監(jiān)督學(xué)習(xí)方法。具體而言,是梯度提升決策樹的一種注重速度和性能的實(shí)現(xiàn)。
提升是一種集成方法,集成方法尋求基于“弱”分類器創(chuàng)建強(qiáng)分類器(模型)。在這一上下文中,弱和強(qiáng)指預(yù)測目標(biāo)變量實(shí)際值的準(zhǔn)確程度。通過在其他模型基礎(chǔ)上迭代地添加模型,前一個(gè)模型的誤差將由下一個(gè)預(yù)測模型糾正,直到達(dá)到滿意的表現(xiàn)。
梯度提升同樣包含逐漸增加模型,糾正之前模型誤差地集成方法。不過,并不在每次迭代中給分類器分配不同的權(quán)重,而是用新模型去擬合之前預(yù)測的新殘差,并最小化加上最新預(yù)測后的損失。
所以,最終將使用梯度下降技術(shù)更新模型,梯度提升由此得名。
關(guān)于XGBoost更多的信息,可以參考我們的XGBoost課程。
XGBoost可以直接通過pip安裝:
pip install xgboost
用于分類的XGBoost模型為XGBClassifier()。創(chuàng)建XGBClassifier()時(shí),max_features可以設(shè)為sqrt,即特征數(shù)的平方根。max_features是尋找最佳分割時(shí)需要考慮的特征數(shù)。所以,假設(shè)n_features為100,那么max_features取值為10.
import xgboost
gbm=xgboost.XGBClassifier(max_features='sqrt', subsample=0.8, random_state=10)
我們使用GridSearchCV()調(diào)整超參數(shù):
GridSearchCV()實(shí)現(xiàn)了fit和score方法。它也同樣實(shí)現(xiàn)了predict、predict_probad、decision_function、transform、inverse_transform方法(如果底層使用的估計(jì)器實(shí)現(xiàn)了這些方法。)
應(yīng)用這些方法的估計(jì)器的參數(shù)是通過在參數(shù)網(wǎng)格上交叉驗(yàn)證、網(wǎng)格搜索得到的。
n_estimators的取值,推薦1、10、100,learning_rate的取值,推薦0.1、0.01、0.5。
n_estimators是提升階段數(shù)。梯度提升對(duì)過擬合的魯棒性相當(dāng)不錯(cuò),因此較大的取值通常意味著更好地表現(xiàn)。
學(xué)習(xí)率。學(xué)習(xí)率可以減慢模型的訓(xùn)練速度,避免過快學(xué)習(xí)導(dǎo)致過擬合。通常將學(xué)習(xí)率設(shè)為0.1到0.3之間的數(shù)字。
通過三折交叉驗(yàn)證,選出最佳learning_rate和n_estimators值。
from sklearn.model_selection importGridSearchCV
parameters = [{'n_estimators': [10, 100]},
{'learning_rate': [0.1, 0.01, 0.5]}]
grid_search = GridSearchCV(estimator = gbm, param_grid = parameters, scoring='accuracy', cv = 3, n_jobs=-1)
grid_search = grid_search.fit(train_X, train_y)
擬合訓(xùn)練集得到了97%的精確度(學(xué)習(xí)率0.5):
grid_search.grid_scores_, grid_search.best_params_, grid_search.best_score_
grid_search.best_estimator_將返回網(wǎng)格搜索得到的最佳模型:
XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1,
colsample_bytree=1, gamma=0, learning_rate=0.5, max_delta_step=0,
max_depth=3, max_features='sqrt', min_child_weight=1, missing=None,
n_estimators=100, n_jobs=1, nthread=None,
objective='binary:logistic', random_state=10, reg_alpha=0,
reg_lambda=1, scale_pos_weight=1, seed=None, silent=True,
subsample=0.8)
使用這一最佳的超參數(shù)組合在訓(xùn)練集上進(jìn)行訓(xùn)練,并在測試集上進(jìn)行預(yù)測。最終得到了96.56%的精確度。
從精確度上來看,我們的模型表現(xiàn)得相當(dāng)不錯(cuò)。然而,果真如此嗎?別忘了,我們的數(shù)據(jù)集是一個(gè)失衡的數(shù)據(jù)集。模型表現(xiàn)到底如何?不能只看精確度。
我們繪制AUROC曲線看看。
from sklearn import metrics
import matplotlib.pyplot as plt
fpr_xg, tpr_xg, thresholds = metrics.roc_curve(y_test, y_pred)
auc_xgb = np.trapz(tpr_xg,fpr_xg)
plt.plot(fpr_xg,tpr_xg,label=" auc="+str(auc_xgb))
plt.legend(loc=4)
plt.show()
果然,在AUROC曲線下,模型原形畢露了。AUC值0.5左右,ROC曲線基本上是對(duì)角線,這是隨機(jī)猜測的水平!
看來,我們真應(yīng)該用些應(yīng)對(duì)失衡分類的技術(shù),例如欠采樣和過采樣,或者SMOTE方法。
由于這篇文章已經(jīng)夠長了,這里就不深入討論如何克服失衡問題了。雖然結(jié)果不如人意,但是我們?nèi)匀煌ㄟ^這個(gè)例子熟悉了機(jī)器學(xué)習(xí)的基本流程。
最后,我們將介紹如何儲(chǔ)存模型,這樣下次預(yù)測就可以直接使用了,不用再費(fèi)時(shí)費(fèi)力地從頭開始訓(xùn)練模型。最簡單直接的方法,就是使用Python的Pickle模塊。
import pickle
XGB_Model_h1b = 'XGB_Model_h1b.sav'
pickle.dump(gbm, open(XGB_Model_h1b, 'wb'))
結(jié)語
創(chuàng)建模型最重要的部分是特征工程和特征選取過程。我們應(yīng)該從特征中提取最多的信息,讓我們的模型更堅(jiān)韌、更精確。特征選取和提取需要時(shí)間和經(jīng)驗(yàn)??赡苡卸喾N處理數(shù)據(jù)集中的信息的方法。
有許多機(jī)器學(xué)習(xí)算法,你應(yīng)該選擇能夠給出最佳結(jié)果的算法。你也可以使用不同的算法然后將它們集成起來。在生產(chǎn)環(huán)境中也可以進(jìn)行A/B測試,以知曉哪個(gè)模型表現(xiàn)更優(yōu)。勇往直前,動(dòng)手編程,嘗試不同的方法??鞓肪幊?!
-
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8481瀏覽量
133864 -
數(shù)據(jù)分析
+關(guān)注
關(guān)注
2文章
1469瀏覽量
34700 -
python
+關(guān)注
關(guān)注
56文章
4822瀏覽量
85874
原文標(biāo)題:Python | 如何使用機(jī)器學(xué)習(xí)預(yù)測H1B簽證狀態(tài)
文章出處:【微信號(hào):jqr_AI,微信公眾號(hào):論智】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
【大語言模型:原理與工程實(shí)踐】大語言模型的預(yù)訓(xùn)練
Python機(jī)器學(xué)習(xí)常用庫
常用python機(jī)器學(xué)習(xí)庫盤點(diǎn)
怎么有效學(xué)習(xí)Python數(shù)據(jù)分析?
什么是探索性測試ET
數(shù)據(jù)探索與數(shù)據(jù)預(yù)處理
探索性數(shù)據(jù)分析(EDA)及其應(yīng)用

設(shè)計(jì)多網(wǎng)絡(luò)協(xié)議的Python網(wǎng)絡(luò)編程的探索性指南
如何構(gòu)建檢測信用卡詐騙的機(jī)器學(xué)習(xí)模型?
細(xì)分模型探索性數(shù)據(jù)分析和預(yù)處理

Sweetviz讓你三行代碼實(shí)現(xiàn)探索性數(shù)據(jù)分析

Sweetviz: 讓你三行代碼實(shí)現(xiàn)探索性數(shù)據(jù)分析

評(píng)論