【云知易】机器学习服务 入门 04 快速上手Notebook

举报
阅识风云 发表于 2017/11/09 15:33:55 2017/11/09
【摘要】 本文通过银行存款预测业务的案例应用,介绍了华为机器学习服务的交互式记事本(Notebook)使用方法,用户可以通过本文快速掌握Notebook的使用和机器学习建模的流程。

一、业务分析

1.1 问题描述

       银行中常见一种业务:根据客户特征(年龄、工作类型、婚姻状况、文化程度、是否有房贷和是否有个人贷款),预测客户是否愿意办理定期存款业务。

1.2 数据分析

       本次演练的数据来自UCI的Machine Learning Repository,地址为https://archive.ics.uci.edu/ml/datasets/Bank+Marketing,数据样例如表1-1所示。我们把获取到的数据保存为“BANK_DATA.csv”,并根据上述网址提供的数据描述信息,编写数据描述文件“BANK.desc”。


表1-1 部分样例数据

年龄
Age
工作类型
Job
婚姻状况
Marital
文化程度
Educatio
n
房贷
Housing
贷款
Loan
标签
Label
58managementmarriedtertiaryyesnono
44techniciansinglesecondaryyesnono
33entrepreneurmarriedsecondaryyesyesno
47blue-collarmarriedunknownyesnono
33unknownsingleunknownnonono
35managementmarriedtertiaryyesnono
28managementsingletertiaryyesyesno


1.3 解决方案

       通过问题描述可知客户办理定期存款只有“是”、“否”两种可能,因此该问题为分类问题中的二分类问题。二分类问题可以用“逻辑回归”或“随机森林”算法来分析处理:

  • 逻辑回归(Logistic Regression)

       逻辑回归算法是一种常用的二分类算法。它的一般处理步骤如下:  

  • 将“样本属于此类”与“样本不属于此类”的概率之比转化成线性函数。

  • 借助极大似然估计对此函数进行参数估计,求得似然函数。

  • 利用梯度下降算法或牛顿法对似然函数最大化求解,不断迭代获得原始问题的最优解,得到逻辑回归模型。

  • 随机森林(Random Forest)

       随机森林算法是数据挖掘中的一种分类方法,用于产生分类模型或回归模型。它用随机的方式建立一个森林,森林由很多决策树组成,每一棵决策树之间没有关联。得到森林之后,当有一个新的样本输入时,就让森林中的每一棵决策树分别进行判断,看这个样本对应哪一类(分类)或哪一个值(回归)。对于分类问题,哪一类被选择最多,就预测这个样本为那一类;对于回归问题,取所有树的预测值的平均值。
       通过数据观察,发现已有数据的线性关系不明显,那么用随机森林算法更好。这里的分类问题可以通过MLS创建包含“随机决策森林”节点的工作流进行分析处理。  


二、上传数据

        待分析的数据需要先上传至OBS,再通过MRS将OBS中的数据导入到HDFS中,供MLS业务分析使用。

2.1 上传数据至 OBS
步骤    登录公有云管理控制台。
步骤2     单击“服务列表”,选择“存储 > 对象存储服务”。
步骤    单击“创建桶”。  并填写表2-1参数配置样例。

表2-1 “创建桶”样例

参数名样例值
区域选择新建桶所在的区域。
桶名称obs-mls


步骤     单击“确定”,创建桶成功。  
步骤5      选择桶“obs-mls”,单击 ,在弹出框中选择待上传的数据文件,确定后,单击“上传”,等待页面提示上传成功。

2.2 通过 MRS 将数据导入 HDFS
步骤1     单击“服务列表”,选择“数据分析 > MapReduce服务”。
步骤2     选择集群“mrs-mls”,单击“文件管理 > 导入”。
步骤3     在弹出框中,选择表2-2中的路径。

表2-2 导入路径

路径说明
OBS路径OBS中待导入的数据文件,例如“s3n://obs-mls/BANK_DATA”。
HDFS路径数据文件导入到HDFS中的路径,例如“/user”。


步骤4     单击“导入”,等待页面提示导入成功。


三、创建交互式记事本

步骤1    登录MLS实例界面,单击左侧导航栏的“项目”,进入项目列表界面。

步骤2    在“bank”项目的“交互式记事本”页签中,单击“创建”。
步骤3    在弹出的“创建交互式记事本”对话框中,“名称”设置为“BankModel_nb”。
步骤4    单击“确定”,创建交互式记事本完成。  


四、编写代码
步骤1    点击进入"BankModel_nb"的交互式记事本编辑界面。
步骤2    编辑代码。该案例应用代码包括数据输入、数据预处理、特征工程、模型构建、模型应用和模型输入输出等6个模板。下面我们把完整的代码拆分成这6个模块分别介绍。
4.1 数据输入

       该流程主要是进行案例样本数据的输入,作为后续步骤中模型构建和应用使用,样例代码如下所示:


  1. # Read input data 
    data_path = u´/user/BANK_DATA.csv´
    rawData = sc.textFile(data_path)

4.2 数据预处理

       数据预处理是指对数据集中的噪声数据进行清洗,避免噪声数据对后续的操作造成影响。在本案例中,主要预处理操作包括删除数据集中表头数据、删除数据集中的逗号以及删除存在未知(unknown)数据的样本,样例代码如下所示:


  1. # delete the header if exists 
    header_flag = False 
    if header_flag: 
        header = rawData.first() 
        rawData = rawData.filter(lambda x: x!= header) 
    #delete comma 
    no_comma_data = rawData.map(lambda x: x.split(´,´)).\ 
                             map(lambda x:[xx.replace(´\´´,´´) for xx in x])  
    #delete unknown data 
    def deleteUnknownForLine(data): 
        flag = True 
        if ´unknown´ in data: 
            flag = False 
        return flag 
    data = no_comma_data.filter(lambda x: deleteUnknownForLine(x)).cache() 
    print(´Preprocess input data done!´)

4.3 特征工程

       在本例子中,数据的类型是字符串格式,因此需要对数据进行重编码,使数据格式便于计算机处理,且满足模型构建的数据格式要求。为此,我们进行了3个处理步骤,分别是特征转换,数据归一化和数据调整。

特征转换

       为了便于计算机处理,我们将数据集中的字符串通过One-**编码成数字,样例代码如下所示:


  1. nominal_index = [1, 2, 3, 4, 5]#column index of category feature 
    def get_mapping(rdd, idx): 
        return rdd.map(lambda fields:fields[idx]).distinct().zipWithIndex().collectAsMap() 
    mappings = [get_mapping(data, i) for i in nominal_index] 
    print(´One-** Encoding:´) 
    print(mappings) 
    #transfer the category feature 
    def transfer_category_feature(data, mappings, nominal_index):  
        cat_len = sum(map(len,[i for i inmappings]))#total number of category feature  
        cat_vec = np.zeros(cat_len)  
        step = 0 
        for index_map, index_data inenumerate(nominal_index): 
            dict_code = mappings[index_map] 
            index =dict_code[data[index_data]] 
            cat_vec[index + step] = 1 
            step = step + len(dict_code) 
        return cat_vec

数据归一化

       为了避免不同特征的数据值差异过大,导致模型性能下降,我们对数据集中的实数进行了归一化处理,使数据分布在0-1之间。样例代码如下所示:


  1. num_index = [0]#column index of real feature 
    def get_max_min(data, num_index): 
        max_col = np.zeros(len(num_index)) 
        min_col =np.zeros(len(num_index))     
        for i, j in enumerate(num_index): 
            data_cols = data.map(lambdafields: fields[j]) 
            max_col =data_cols.reduce(lambda x,y:max(x,y)) 
            min_col =data_cols.reduce(lambda x,y:min(x,y)) 
        return  [max_col, min_col]   
    [max_col, min_col] = get_max_min(data, num_index) 
    def normalize_real_feature(data, num_index, max_col, min_col):         
        num_vec = np.zeros(len(num_index)) 
        for i, j in enumerate(num_index): 
            num = float(data[j]) 
            num_vec = (num -min_col)/(max_col - min_col) 
        return num_vec

数据调整

       为了使数据集格式满足训练模型时的输入要求,需要对数据集进行调整,在本案例中,输入数据集要求每个样本的第一列为样本标签,其他列为特征值,样例代码如下所示:


  1. from pyspark.mllib.regression import LabeledPoint 
    def extract_label(data): 
        label = 1 if data[-1] == ´yes´ else 0
        return label 
    def extract_features(data, mappings, num_index, nominal_index, max_col,min_col):  
        category_features =transfer_category_feature(data, mappings, nominal_index) 
        real_features =normalize_real_feature(data, num_index, max_col, min_col)     
        feature =  np.concatenate((category_features,real_features)) 
        return feature 
    label_feature = data.map(lambda point: LabeledPoint(extract_label(point), \ 
                   extract_features(point, mappings, num_index, nominal_index, max_col,min_col)))   
    print(label_feature.first())

4.4 模型构建

       本案例中,采用随机森林算法进行模型的构建,采用pySpark.mllib原生的随机森林函数进行训练。模型构建包括两个过程,分别是数据集拆分(拆分成训练数据集和测试数据集)和模型训练,样例代码如下所示:


  1. from pyspark.mllib.tree import RandomForest 
    (trainData, testData) = label_feature.randomSplit([0.7, 0.3])  
    model = RandomForest.trainClassifier(trainData, numClasses = 2, 
                          categoricalFeaturesInfo={}, 
                          numTrees = 10, featureSubsetStrategy="auto", 
                          impurity = ´gini´, maxDepth = 10, maxBins = 50) 
    print(´Train model done.´)

4.5 模型应用

       模型应用主要包括模型的评估和预测。在本案例中,我们选取了测试数据集进行模型评估和模型的预测演示。

模型评估

       模型评估是指采用多种评估方法,根据测试数据集的预测结果对模型的性能进行评估,判断该模型是否能满足用户需求。在本案例中,我们采用了AUC和PR曲线下方面积两种评估方法,样例代码如下所示:


  1. from pyspark.mllib.evaluation import BinaryClassificationMetrics 
    scores = new_model.predict(testData.map(lambda x: x.features)) 
    all_models_metrics = [] 
    scoresAndLabels = testData.map(lambda x: x.label).zip(scores) 
    metrics = BinaryClassificationMetrics(scoresAndLabels)  #evalution 
    all_models_metrics.append((model.__class__.__name__, metrics.areaUnderROC,\ 
                                metrics.areaUnderPR)) 
    for modelName, AUC, PR in all_models_metrics: 
        print (´AUC is %f, PR is %f´%(AUC,PR)) 
    print(´Evalution model done.´)

模型预测

       模型预测是指根据已训练好的模型,对新的数据集进行预测,得到新数据集中每个样本的标签。在本案例中,我们采用测试集来模拟新的数据进行模型预测操作,样例代码如下所示:


  1. result = new_model.predict(testData.map(lambda x: x.features)) 
    print(result.take(30))


4.6 模型输入输出

       模型的输入输出主要包括模型的保存和模型的导入,通过模型的输入输出,用户可以把训练好的并且性能满足要求的模型保存下来,下次使用时,直接导入已保存的模型进行应用,无需重复进行模型训练。

模型输出

       模型的输出是指对已训练好的模型进行保存,用于后续使用,样例代码如下所示:


  1. model_save_path = u´/user/RFModel´       
    model.save(sc, model_save_path)


模型输入

      模型的输入是指导入已经保存好的模型文件,直接进行模型预测,省去了模型训练过程,样例代码如下所示:


  1. from pyspark.mllib.tree import RandomForestModel 
    model_path = u´<your path>/RFModel´ 
    new_model = RandomForestModel.load(sc, model_path)#load model 
    print(´Load model done.´


更多内容,请参见机器学习服务帮助中心https://support.huaweicloud.com/mls/index.html)。

jiemian.jpg

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。