机器学习-以自闭症判别为例

117 阅读5分钟

在先前已经简单介绍了机器学习的基本理论# python机器学习笔记,下面对其进行简单应用。

本文主要内容为应用基础的机器学习,对自闭症数据集进行分析,以预测是否某个个体患有自闭症。下面利用代码注释的方式对流程进行介绍,并且会在代码末尾附上运行结果。

1、导包

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
sns.set_theme(style="white", 
              palette="pastel")

import warnings
warnings.filterwarnings('ignore')

2、数据探索以及特征工程

2.1 加载数据

train=pd.read_csv('./input/02.train.csv') #训练集
test=pd.read_csv('./input/02.test.csv') #测试集

2.2、数据查看与预处理

2.2.1、查看部分数据

#查看训练集前10个数据
# 下面只给出此查看结果图片
train.head(10)
# 查看测试集前十数据
test.head(10)
# 随机查看训练集中十个数据
train.sample(10)
# 随机查看测试集中十个数据
test.sample(10)

image.png

2.2.2、查看行列大小

#查看数据行列大小
row_size_and_col_size=pd.DataFrame(columns=['train','test'])
row_size_and_col_size.loc['row']=[train.shape[0],test.shape[0]]
row_size_and_col_size.loc['col']=[train.shape[1],test.shape[1]]
row_size_and_col_size

image.png

2.2.3、查看各列名字以及重命名

df_col=pd.DataFrame([train.columns,test.columns]).T
df_col.rename(columns={0:'train',1:'test'},inplace=True) 
df_col

image.png

# 从上表可以看出,austim、contry_of_res、Class/ASD的列名存在问题
# 对问题列进行修改
train=train.rename(columns={'austim':'autism',
                     'contry_of_res':'country_of_res',
                     'Class/ASD':'Class'
                     })
test=test.rename(columns={'austim':'autism',
                     'contry_of_res':'country_of_res',
                     'Class/ASD':'Class'
                     })
                     
# 验证是否修改成功
df_col=pd.DataFrame([train.columns,test.columns]).T
df_col.rename(columns={0:'train',1:'test'},inplace=True) 
df_col

image.png

2.2.4、查看各列是否有缺失值以及填充

# 查看训练集与数据集各列是否有缺失值
# 可以看出各列没有缺失值,不必作填充预处理
df_lost=pd.DataFrame([train.isnull().sum(),test.isnull().sum()]).T
df_lost.rename(columns={0:'train',1:'test'},inplace=True)
df_lost

image.png

2.2.5  查看各列有几种值以及删除无效特征

# 查看训练集各列有几种值
train.nunique()
# 查看测试集各列有几种值
test.nunique()

image.png

# 可以看出 age_desc 是种类只有一种,是无效的,因此将其删除
train.drop(columns=['age_desc'], inplace=True)
test.drop(columns=['age_desc'],inplace=True)
# 以及ID是人为后给定的,应该删除
train.drop(columns=['ID'], inplace=True)
test.drop(columns=['ID'],inplace=True)
# 查看是否修改成功
df_col=pd.DataFrame([train.columns,test.columns]).T
df_col.rename(columns={0:'train',1:'test'},inplace=True) 
df_col

image.png

2.2.6  具体查看各列值以及标准化

#非数值的列名数组
no_value=['gender','ethnicity','jaundice','autism','country_of_res','used_app_before','relation']
# 查看训练集中非数值型列里面各有什么值
for v in no_value:
    print(v+":")
    print(train[v].unique())
# 查看测试集中非数值型列里面各有什么值
for v in no_value:
    print(v+":")
    print(test[v].unique())

image.png

image.png

# 其中ethnicity中出现了"?"以及"others"和"Others",应该作出处理
train['ethnicity']=train['ethnicity'].replace('?','Others')
train['ethnicity']=train['ethnicity'].replace('others','Others')
test['ethnicity']=test['ethnicity'].replace('?','Others')
test['ethnicity']=test['ethnicity'].replace('others','Others')
#查看训练集是否修改成功
train['ethnicity'].unique()
#查看测试集是否修改成功
test['ethnicity'].unique()

image.png

image.png

# 其中relation中出现了,应该作出处理,用出现次数最多的值替换'?'
train['relation']=train['relation'].replace('?',train['relation'].mode()[0])
test['relation']=test['relation'].replace('?',test['relation'].mode()[0])
#查看训练集是否修改成功
train['relation'].unique()
#查看测试集是否修改成功
test['relation'].unique()

image.png

image.png

2.2.7  查看各列类型以及标签编码

# 对比查看测试集与训练集数据类型
df_type=pd.DataFrame([train.dtypes,test.dtypes]).T 
df_type.rename(columns={0:'train',1:'test'},inplace=True)
df_type
# 可以看出,训练集与测试集各列的数据类型是一致的(除了Class)

image.png

#需要将非数值型变量转换
#先导入相关包
from sklearn import preprocessing
#导入标签编码器
lable_encoder=preprocessing.LabelEncoder()
#非数值的列名数组
no_value=['gender','ethnicity','jaundice','autism','country_of_res','used_app_before','relation']
#将非数值型数据转化为数值型
for name in no_value:
    name=str(name)
    train[name]=lable_encoder.fit_transform(train[name])
    test[name]=lable_encoder.fit_transform(test[name])
# 查看是否修改成功
df_type=pd.DataFrame([train.dtypes,test.dtypes]).T 
df_type.rename(columns={0:'train',1:'test'},inplace=True)
df_type

image.png

2.2.8  查看各列简要信息

#查看训练集简要信息
train.info()
#查看测试集简要信息
test.info()

image.png

image.png

2.2.9  查看统计信息

# 查看训练集统计信息
train.describe()
# 查看测试集统计信息
test.describe()

image.png

image.png

2.3  数据可视化

2.3.1  查看自闭症人群在训练集中的分布

sns.countplot(data=train,x='Class')

image.png

2.3.2  查看不同因素下自闭症人群的分布

### 因为数值型变量往往具有较多值,因此取原非数值的几个变量探究
# no_value=['gender','ethnicity','jaundice','autism','country_of_res','used_app_before','relation']
cat_feats = train.loc[:,no_value]
for feat in cat_feats:
    plt.figure(figsize=(15, 6))
    sns.countplot(data=train, x = feat, hue='Class')
    plt.title(f'Distribution {feat}', fontsize=15)
#因为图片较多,下面只截取一张

image.png

 ### 查看是否是自闭症与其他因素的相关性
relevance=train.corr()['Class'].sort_values(ascending=False)[1:]
relevance.to_frame().plot.bar(figsize=(12,5))

image.png

# 通过热力图查看各因素之间的相关性
plt.figure(figsize=(15, 10))
sns.heatmap(train.corr(), annot=True)
plt.show()

image.png

3  模型建立

3.1  导包

from sklearn.metrics import classification_report
from sklearn.metrics import accuracy_score, f1_score, confusion_matrix,classification_report,roc_auc_score, roc_curve,auc,precision_score

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import BaggingClassifier
import xgboost as xgb
from lightgbm import LGBMClassifier


from sklearn.preprocessing import StandardScaler

3.2  数据切分

X = train.drop(["Class"], axis=1)
Y = train["Class"]
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, train_size=0.2, random_state=42)

3.3  定义查看模型评价指标函数

# 模型训练及输出评价指标
def result(model, X_train, Y_train, X_test, Y_test):
    
    # fit on data
    model.fit(X_train, Y_train)
    
    # prediction
    pred = model.predict(X_test)
    
    # performance of model
    print("Classification Report: \n", classification_report(Y_test, pred))
    print("-" * 100)
    print()
    
    # accuracy of model
    acc = accuracy_score(Y_test, pred)
    accuracy_list.append(acc)
    print("Accuracy Score: ", acc)
    print("-" * 100)
    print()

    # f1-score of model
    f1 = f1_score(Y_test, pred)
    f1_list.append(f1)
    print("F1 Score: ", f1)
    print("-" * 100)
    print()

    # roc-auc curve of model
    fpr,tpr,threshold = roc_curve(Y_test,pred)
    auc_value = auc(fpr, tpr)
    rocauc_score = roc_auc_score(Y_test, pred)
    roc_auc_list.append(rocauc_score)
    plt.figure(figsize=(5,5),dpi=100)
    print("ROC-AUC Score: ", f1)
    print("-" * 100)
    print()
    
    plt.plot(fpr,tpr,linestyle='-',label = "(auc_value = %0.3f)" % auc_value)
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.legend()
    plt.show()
    print()
    
    # confusion matrix for model
    print("Confusion Matrix: ")
    plt.figure(figsize=(10, 5))
    sns.heatmap(confusion_matrix(Y_test, pred), annot=True, fmt='g');
    plt.title('Confusion Matrix', fontsize=20)
    
accuracy_list=[]
f1_list=[]
roc_auc_list=[]

3.4  利用不同模型训练

3.4.1  XGB

xgb_classifier =xgb.XGBClassifier()
result(xgb_classifier,X_train, Y_train, X_test, Y_test)
#因为模型较多,只在XGB模型中截图

image.png

image.png

image.png

3.4.2  LGB

lgb_classifier =LGBMClassifier()
result(lgb_classifier,X_train, Y_train, X_test, Y_test)

3.4.3  逻辑回归

lr=LogisticRegression()
result(lr,X_train, Y_train, X_test, Y_test)

3.4.4  KNN

KNC=KNeighborsClassifier()
result(KNC,X_train, Y_train, X_test, Y_test)

3.4.5  随机森林

RFC=RandomForestClassifier()
result(RFC,X_train, Y_train, X_test, Y_test)

3.4.6  GradientBoosting

GBC=GradientBoostingClassifier()
result(GBC,X_train, Y_train, X_test, Y_test)

3.4.7  BaggingClassifier

BC=BaggingClassifier()
result(BC,X_train, Y_train, X_test, Y_test)

3.5  对比各模型效率

3.5.1  综合对比

# 所使用的模型列表
classifier_list=['XGB','LGB','LogisticRegression','KNN',
                 'RandomForest','Gradient Boosting',
                 'BaggingClassifier']
list_class=[]
for i in range(0,len(classifier_list)):
    listclass=[accuracy_list[i],f1_list[i],roc_auc_list[i]]
    list_class.append(listclass)
list_class=pd.DataFrame(list_class,index=classifier_list)
list_class.rename(columns={0:'Accuracy Score',1:'F1 Score',2:'ROC-AUC Score'},inplace=True)
list_class

image.png

# 可视化
list_class.plot.bar()

image.png

3.5.2  通过Accuracy Score对比

# 根据Accuracy Score排序
list_class.sort_values(ascending=False,by='Accuracy Score')

image.png

# 可视化
plt.figure(figsize=(8,6))
sns.barplot(x=list_class['Accuracy Score']*100,
            y=list_class.index,
            data=list_class,
            order=list_class.sort_values('Accuracy Score',ascending=False).index
)

image.png

3.5.3  通过F1 Score对比

# 根据F1 Score排序
list_class.sort_values(ascending=False,by='F1 Score')

image.png

# 可视化
plt.figure(figsize=(8,6))
sns.barplot(x=list_class['F1 Score']*100,
            y=list_class.index,
            data=list_class,
            order=list_class.sort_values('F1 Score',ascending=False).index
)

image.png

3.5.4  通过ROC-AUC Score对比

# 根据ROC-AUC Score排序
list_class.sort_values(ascending=False,by='ROC-AUC Score')

image.png

# 可视化
plt.figure(figsize=(8,6))
sns.barplot(x=list_class['ROC-AUC Score']*100,
            y=list_class.index,
            data=list_class,
            order=list_class.sort_values('ROC-AUC Score',ascending=False).index
)

image.png

3.6  模型调参

# 由3.5 可以看出,随机森林有着较好的性能,因此对随机森林进行调参
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV

# X_train, X_test, Y_train, Y_test = train_test_split(X, Y, train_size=0.2, random_state=42)

params = {"max_features":("log2", "sqrt")}
 
gsearch = GridSearchCV(estimator=RandomForestClassifier(n_estimators=800, max_depth=800, min_samples_split=14), param_grid = params, scoring = "neg_log_loss")
gsearch.fit(X_train, Y_train)
  
print("best params")
 
print(gsearch.best_params_)
 
print("best scores")
 
print(gsearch.best_score_)

gsearch.best_estimator_.fit(X,Y)

pre=gsearch.best_estimator_.predict(X_test)

print(classification_report(pre,Y_test))

image.png

# 在RandomForestClassifier(max_depth=800, max_features='sqrt', min_samples_split=14,n_estimators=800)
# 条件下对比未调参数有着较大提升(参考3.4.5)

4、预测

# 利用上面得到的模型对测试集进行预测
ans=gsearch.best_estimator_.predict(test)