数据挖掘:一个end2end完整实例

这里展示一个完整的数据挖掘实例,以供参考。数据挖掘是为了从数据中挖掘出有用的信息,提供决策依据,data driven decision making,而不是people driven或者boss driven。(减少拍脑袋有助于减少脱发,不信看你们公司大佬们都脱成啥样了)

首先,必须明确需求和目标,要知道自己想干什么和想达到什么。否则不就是瞎搞么,此处又要实名diss吉利了(我为吉利默哀三秒,重拾这个号就是为了黑吉利的,难道是为了传道授业解惑啊,黑吉利是我创作的动力源泉,感谢源泉最近的所作所为让我力量爆表)。

在我们的例子中,我们用亚马逊的一个数据集作为例子,它的目标是为了预测新员工入职时是否需要某项权限。通过模型来预测,协助人工操作。

然后我们开始数据挖掘的步骤。

第一步:收集和准备数据。我们就从kaggle或catboost.dataset上直接下载好了(https://www.kaggle.com/c/amazon-employee-access-challenge),省去这烦心的一步。真实场景中,好的数据比模型和优化还要重要,是关键的第一步。为什么工业的数字化转型这么艰难,主要是数据太差了。

第二步:数据划分。数据可以划分成训练集、验证集和测试集。训练数据是用来建立模型的,验证集是用来验证结果、调参的,测试数据是用来评估模型的。虽然测试集是用来评估模型的,但是不能根据测试集结果来调整模型和参数,而应该根据验证集来做。例如我们下载的数据集里有test_data,但必须从train_data继续划分,可以留一部分20%验证,也可以采用交叉验证的方式。我们这里就用交叉验证的方法:就像这样。每次用80%的数据训练,留20%验证。5次之后,所有数据都参与了训练;所有数据也都参与了验证。

第三步:查看数据。基本的看看我们有多少数据,多少特征,每个特征是什么类型。

  (32769, 10) (58921, 10)
   ACTION  RESOURCE  MGR_ID  ...  ROLE_FAMILY_DESC  ROLE_FAMILY  ROLE_CODE
0       1     39353   85475  ...            117906       290919     117908
1       1     17183    1540  ...            118536       308574     118539
2       1     36724   14457  ...            267952        19721     117880
3       1     36135    5396  ...            240983       290919     118322
4       1     42680    5905  ...            123932        19793     119325

[5 rows x 10 columns]

所以能看出来,训练的数据有32769个样本,每个样本有10列,其中ACTION列就是我们想要的预测值,其他9列就是所谓的特征。测试的样本有58921个,这么多应该是可以充分的评估模型的好坏了。

我们要预测的是action,可以查看一下目标action的分布。目标只包含有0和1两种变量。目标是0 的有1897,目标是1 的有30872,加在一起就是我们的训练样本总数32769。关于这里的0和1的不平衡,后述再讲好了。

第四步:关键的一步建立完整pipeline。pipeline包括搭建模型所需要的各个部分,从数据导入、数据预处理、特征工程、模型搭建、模型评估等。

一般pipeline开始的模型采用简单的baseline模型就可以了,这里既然是一个二分类,采用常见的逻辑回归模型就可以了(同,后续再详细介绍)。

数据加载部分,包括画出上面的图的部分

def load_data(data_dir,plot=False):
    train = pd.read_csv(data_dir+'/train.csv')
    test = pd.read_csv(data_dir+'/test.csv')
    print(train.values.shape,test.values.shape)
    print(train.head(5))
    print(np.unique(train.loc[:,['ACTION']]))

    if plot:
        dis=train.groupby(['ACTION']).size().reset_index(name='size')

        plt.bar(dis['ACTION'].astype('int'),dis['size'],color='lightblue')
        for a, b in zip(dis['ACTION'], dis['size']):
            plt.text(a, b + 0.05, '%.0f' % b, ha='center', va='bottom', fontsize=10)
            plt.text(a, b/3, '%.0f'%a, ha='center',va='bottom',fontsize=15,color='blue')
        plt.show()
    return train,test

特征转换部分,这里的特征全都是类别特征。转化为one-hot特征,one-hot是这样的。虽然表面上他们是0,1,2,3来表示,其实可能代表的是质量、研发、产品、售后四个部门,他们之间并没有0到1到2,这样的数字递进关系,就每一个转化为一个维度好了。





def transform_feature(data,feature_cols,target_cols=None,training=False):
    if training:
        assert target_cols is not None
        oh = OneHotEncoder(sparse=True, dtype=np.float32, handle_unknown='ignore')

        x=oh.fit_transform(data.loc[:,feature_cols])
        with open("encoder", "wb") as f:
            pickle.dump(oh, f)

        y=data[target_cols].values
        print(x.shape,y.shape)
        return x,y

    with open('encoder','rb') as f:
        oh = pickle.load(f)
    x=oh.transform(data.loc[:,feature_cols])
    return x

生成模型部分,这里采用最简单的线性模型,逻辑回归。

seed=2020

def create_model():
    model = LogisticRegression(
        penalty='l2',
        C=1.0,
        fit_intercept=True,
        random_state=seed,
        solver='liblinear',
        max_iter=1000,
    )
    return model

交叉验证模型评估部分,这就是上面图里,分成5份,每份分别来验证。

def validate_model(x,y,model,metrics):
    skf = StratifiedKFold(n_splits=5, random_state=seed, shuffle=True)
    re=[]

    for train_index, test_index in skf.split(x, y):
        print("TRAIN:", len(train_index), "TEST:", len(test_index))
        x_train, x_test = x[train_index], x[test_index]
        y_train, y_test = y[train_index], y[test_index]

        model.fit(x_train,y_train)
        y_pred=model.predict_proba(x_test)[:,1]

        re.append(metrics(y_test,y_pred))

    print(re)

生成测试结果部分,最后把测试集预测处理,评估以下模型。

def predict(model,x_test):
    predictions = model.predict_proba(x_test)[:, 1]
    print(predictions)
    return predictions

把上述各个部分串联起来的主函数部分

def main():
    train,test=load_data(data_dir='../data/amazon-employee-access-challenge')

    feature_cols=[i for i in train.columns if i not in ['ACTION','ROLE_TITLE']]
    target_cols='ACTION'
    x,y=transform_feature(train,feature_cols=feature_cols,target_cols=target_cols,training=True)

    model=create_model()
    result=validate_model(x,y,model,metrics=roc_auc_score)

    x_test = transform_feature(test, feature_cols=feature_cols,target_cols=None,training = False)
    predict(model,x_test)
    
if __name__=='__main__':
    main()  

第五步:根据验证结果持续优化,来取得最终模型和参数。这里,优化暂不展开来讲,下一篇数据挖掘II中会详细介绍如何进一步的优化。I肯定要写的,优化才是我日常主要工作、但是却不擅长的部分。为了保住自己的工作,不去吉利这样的公司,一定会慢慢写起来的。

第六步:在测试集上评估结果,如果结果也是满意的,则准备分析报告或上线。二分类最常用的评估措施,可以查看准确率、召回率、F1、AUC等。他们都基于以下矩阵:

即使是简单的逻辑回归模型,5次取不同数据也可以达到 [0.863, 0.856, 0.861, 0.867, 0.85],也就是我们评估这个模型可以达到85%~86%的准确率。这已经是可以接受的结果了。在二分类,即使是瞎蒙,最少也会有50%的概率。为什么说最少呢,二者在平衡的时候,瞎蒙的概率是最低的。如果像实例中1的个数远远大于0的个数,全部都蒙1也会有百分之七八十的准确率。所以才会有上述的不同度量方法来解决这个问题。

以上,差不多就是一个完整的数据挖掘过程。参考以下链接

  • https://www.kaggle.com/dmitrylarko/kaggledays-sf-1-amazon-baseline

最后,日常apprecriate黑吉利(black geely)的邀请,故有此文。But,我只是顺手黑一黑,毫无恶意的。I’m still nice, and black geely is my friend。我是YueTan,完整代码在知识星球分享和github

欢迎关注我的公众号:YueTan

你可能感兴趣的:(数据挖掘,python,机器学习,人工智能)