
一只小鱼哲
传统的防窃漏电方法主要通过定期巡检、定期校验电表、用户举报窃电等方法来发现窃电或计量装置故障。但这种方法对人的依赖性太强,抓窃查漏的目标不明确。 目前,很多供电局主要通过工作人员利用计量异常报警功能和电能量数据查询功能开展用户用电情况的在线监控工作,通过采集电量异常、负荷异常、终端报警、主站报警、线损异常等信息监测窃漏电情况和发现计量装置的故障。根据报警事件发生前后客户计量点有关的电流、电压、负荷数据情况等,构建基于指标加权的用电异常分析模型,实现检查客户是否存在窃电、违章用电.及计量装置故障等。 以上防窃漏电的诊断方法,虽然能获得用电异常的某些信息,但由于终端误报或漏报过多,无法达到真正快速精确定位窃漏电嫌疑用户的目的,往往令稽查工作人员无所适从。而且在采用这种方法建模时,模型各输人指标权重的确定需要用专家的知识和经验来判断,具有很大的主观性,存在明显的缺陷,所以实施效果往往不尽如人意。 现有的电力计量自动化系统能够采集到各相电流、电压、功率因数等用电负荷数据以及用电异常等终端报警信息。异常告警信息和用电负荷数据能够反映用户的用电情况,同时稽查工作人员也会通过在线稽查系统和现场稽查来找出窃漏电用户,并录入系统。 通过这些数据信息提取出窃漏电用户的关键特征,构建窃漏电用户的识别模型,就能自动检查、判断用户是否存在窃漏电行为,大大降低稽查工作人员的工作量,保障人民的正常用电,安全用电。 载入数据并进行数据探索 选择好数据集之后,里面是一个用户的三个窃漏电指标以及用户是否真实窃漏电的数据。其中包括:电量趋势下降指标,线损指标,告警类指标数量 以及 是否窃漏电。 这里我们可以通过从左侧 组件-统计分析 拖入相关系数矩阵这个组件,来观察各个特征对于输出电力。 右键单击完成的组件,选择查看分析报告,就可以得到我们的相关性分析了。从这张相关性图中,我们会发现,其实这三个指标对于最终是否为窃电用户的关系都不是特别明显,也就是说决定用户是否为窃电用户的特征并不明显的具有单一性。此时我们还可以通过左侧的 组件-统计分析 拖入数据视图 来分析各个特征对于我们的标签列的数据分布。我们只需要按照如下配置选择特征列 然后选择我们的标签列 最后我们同样右键单击从此处开始运行后,右键单击完成的组件,选择查看分析报告,就可以看到各个特征和标签列在数据分布上的关系。 对数据进行建模 完成简单的探索性分析之后,我们就可以开始选择合适的算法模型建模了。我们可以先通过 组件-数据预处理 中的拆分组件 对数据做一次拆分,将数据分为训练集和测试集。 然后我们可以使用组件-机器学习-回归 中的逻辑回归二分类 来对我们的数据进行回归建模。这里我们需要选择我们的特征列(X)和我们的标签列(Y) 这里我们的特征列就选择 : power_usage_decline_level,line_loss_rate 和 warning_num 对回归模型进行预测和评估 建模完毕之后,我们可以通过 组件-机器学习 中的预测来预测该模型在测试数据集上的效果。特征和原样输出我们都可以默认全选。然后我们再从左侧的 组件-机器学习-评估 中选择二分类评估 即可获得我们的模型效果 这时候整个实验的应该如下图: 右键我们完成运行的二分类评估组件,即可看到我们的模型效果。这里我们的AUC达到了 0.9827, 效果非常不错。 这样我们就通过机器学习PAI平台完成了用户窃电行为的识别。我们可以通过EAS在线部署将这个服务部署为可在线调用的服务,为电网提供用户窃电行为的在线识别服务. 本实验参考了《Python数据分析与挖掘实战》,如有版权等问题,请联系本文作者。我们尊重学术领域每一位研究者们对于学术的贡献,致力将技术和现实生活更好的结合应用落地。
前言 机器学习很多时候在工业场景下也会有非常好的应用。本次实验,我们就会以一个综合循环发电厂的发电数据来展示机器学习是如何应用到工业生产的实际场景中的。 本实验数据采集自 UCI 机器学习数据集中的 混合发电厂数据。对于发电厂来说,风力发电的输出电力很大情况下决定了单位发电机能够生产的电能。因此,通过收集系统各个相关指标来预测最终的输出电力对于发电厂来说是非常有帮助的。有效的预测发电机的输出电力可以更好的评估安排电力生产计划,避免资源的浪费。 载入数据并进行数据探索 载入好数据集之后,里面是一个综合循环发电场的数据,一共有9568个样本数据。每个数据有5列,分别为:AT(温度), V(压力), AP(湿度), RH(压强), PE(输出电力)。下面是数据预览的截图: 然后为了找出对 PE 输出电力影响最大的因素,我们可以从左侧 组件-统计分析 拖入相关系数矩阵这个组件,来观察各个特征对于输出电力。 右键单击完成的组件,选择查看分析报告,就可以得到我们的相关性分析了。从这张相关性图中,我们不难看到和 输出电力最相关的因素就是 温度,其次是 压力,然后是湿度,再然后是压强。 对数据进行建模 观察完数据相关性之后,我们可以通过 组件-数据预处理 中的拆分组件 对数据做一次拆分,将数据分为训练集和测试集。然后再使用 组件-机器学习-回归 中的线性回归 来对我们的数据进行回归建模。这里我们需要选择我们的特征列(X)和我们的标签列(Y) 对回归模型进行预测和评估 建模完毕之后,我们可以通过 组件-机器学习 中的预测来预测该模型在测试数据集上的效果。只需要进行如下的配置即可 特征列我们选择 at,v,ap,rh 原样输出列我们全选即可。 我们在这一步完成之后可以右键模型,点击查看模型 即可看到不同的特征对于我们的结果量的权重 最后,再从左侧的 组件-机器学习-评估 中选择回归模型评估即可获得我们的模型效果。右键 回归模型评估-查看分析报告 即可发现我们的 RMSE 到达了 4.57。下面是整个实验完成后的截图 这样我们就通过线性回归模型建立了一个混合发电厂的发电电力预测模型。通过模型部署之后,我们就可以实时的为发电厂提供发电电力的预估,以便更好的安排电力的生产计划,避免资源浪费。
前情提要 人工智能千千万,没法落地都白干。自从上次老司机用神经网络训练了热狗识别模型以后,群众们表示想看一波更加接地气,最好是那种能10分钟上手,一辈子受用的模型。这次,我们就通过某著名电商公司的公开数据集,在阿里云大数据生态之下快速构建一个基于协同过滤的推荐系统! 推荐系统大家都不陌生,早就已经和大家的生活息息相关。从淘宝天猫的猜你喜欢,到抖音快手的向你推荐,再到新浪微博的热点推荐,推荐系统让大家又爱又恨。可是这无数的推荐系统背后的原理到底是如何构成的?今天就让数据科学老司机带你一起在5块钱以内构建一个基于协同过滤的推荐系统,为你揭开数据的秘密。 常见推荐系统原理 在开始之前,我们先讲讲常见的推荐系统的原理: 基于热度的推荐系统: 最简单,但是也是最不个性化的。典型的案例就是 bilibili 的日/周/月榜 基于内容的推荐系统: 基于内容描述的推荐系统 基于协同过滤的推荐系统: 基于用户相似度的推荐系统 但是用户和用户之间的相似度是如何定义的呢?其实这个数值的计算方式有很多种。这一次我们选择一个相对简单易懂的计算方式: Jaccard相似系数 具体计算公式如下 给定两个集合A,B,Jaccard 系数定义为A与B交集的大小与A与B并集的大小的比值。Jaccard 距离越大,样本相似度越低。也就是说 如果2个用户的 Jaccard 得分为越高,这两个用户越相似。反之同理。 那么原理就说到这里,然后我们就进入实战环节。整个实验的架构图如下: 数据集解读 这一次我们选择从 UCI 开放数据集中的 在线购买商品数据集 来作为案例。这个数据集有 2010 年 1月 12日 到 2011年 9月 12日的一家 英国的网上电商所有的交易数据。这家公司主要是出售各种各样神奇的小礼物的。我们这里可以用天池的Notebook(免费的)来做一个简单的EDA和数据清洗。大家也可以直接下载我为大家准备好的数据清洗代码和数据集 下载之后直接运行 EDA_CN.py 即可。当然也可以看一下里面的Notebook。 载入数据集之后,我们可以看到我们的数据一共有55万条记录左右。 但是再仔细观察一些,发现空值还是很多的 我们可以丢弃这些空值,然后再重新导出数据集。 导出之后,我们可以随便找一台能够链接外网的 ECS 实例,把数据上传上去。我这里个人推荐可以用 FileZilla ,免费好用。阿里云的ECS是按月付费的,我们可以先短暂购买一下,用完之后释放就可以了。一个2核8G基础的ECS实例成本平摊到每天也就 2 块钱不到,远低于我们的 5块钱的经费。 服务开通 - 开通 PAI 和 DW(DataWorks) 准备好数据集之后,我们就可以开始准备我们在阿里云大数据平台上的环境配置了。可以先参考这个 PAI开通流程 开通 机器学习 PAI,并且创建可视化建模服务。完成之后,我们如果登陆 PAI 工作台 和 DataWorks控制台 应该就可以看到我们刚刚创建的工作空间了。 DW 添加数据源 + 数据集成 + 验证 确认完工作空间创建之后,我们先登陆 DataWorks控制台 来进行数据集成,把我们刚刚清洗好的数据给上传到 MaxCompute 里面。 进入工作空间后,我们可以参考 FTP 数据源配置 先配置一个FTP数据源。 创建完成之后,我们在回到控制台,进入数据开发。 进入之后,我们可以跟着系统的引导,创建一个业务流程。比如我这里就创建了一个名为 测试 的业务流程 创建完毕之后,我们可以双击数据集成,然后创建一个新的数据集成任务。选择我们刚刚添加的数据源,以及对应的表。这里我们可以先通过在数据开发中运行如下的 SQL 来创建一张我们的表。 -- 创建数据源 CREATE TABLE IF NOT EXISTS uci_e_commerce_data_clean ( InvoiceNo STRING COMMENT 'InvoiceNo', StockCode STRING COMMENT 'StockCode', Description STRING COMMENT 'Description', Quantity BIGINT COMMENT 'Quantity', InvoiceDate STRING COMMENT 'InvoiceDate', UnitPrice DOUBLE COMMENT 'UnitPrice', CustomerID DOUBLE COMMENT 'CustomerID', Country STRING COMMENT 'Country' ) COMMENT 'UCI E-Commerce DATASET ' lifecycle 36000; 然后我们再完成我们的数据集成配置。 选中我们刚刚创建的 uci_e_commerce_data_clean 之后,下方应该会自动出现表名匹配的界面。 然后再拉到地步看一下通道控制,这里我们用默认的就可以了。然后我们按下左上方的运行按钮,就会看到我们任务开始运行了。等到跳出的日志显示任务完毕之后,我们可以在左侧的公共表中看一下,验证我们的数据上云是否成功。 能看到数据就说明我们的数据已经成功的从我们的ECS里面到我们的MaxCompute环境了。接下来就是构建我们的协同过滤模型的事情了。 PAI构建模型 首先,我们登陆到我们的 PAI 工作台,进入我们刚刚创建的 PAI-Stuido 实例。进入实例之后,我们新建一个实验。 然后打开这个实验,我们可以从左侧数据源内搜索我们刚刚迁移到MaxCompute到表名,然后将它拖入主界面。然后我们再拖入SQl组件来做好数据类型的转换。SQL内容如下: -- 类型转换 select cast(cast(customerid AS BIGINT) AS STRING) customerid, REPLACE(description, ' ', '-') description from ${t1} ; 完成类型转换之后,我们就可以拖入我们的协同过滤算法了,并为其设置好相对应的字段。 同时我们可以吧参数也更改一下,因为保留2000个最相近的物品对我们来说计算量有些太大,而且也没必要。 最后我们再添加一个SQL组件来把协同过滤组件计算出来的结果全部读取出来 语句为SELECT * FROM ${t1};,看一下长什么样。整个实验的图现在应该为如下: 确认无误之后,我们点击开始运行实验,就可以看到我们的实验正在运行了。等实验运行完毕之后,我们可以右键点击我们的最后一个SQL组件来查看结果数据。数据结果如下: 图上标红的就是我们计算结果存储的表名。接下来我们就可以进行清洗这个结果数据,将它部署为一个接口服务。 生成接口服务 我们先进入Dataworks的控制台,找到我们之前用过的工作空间。进入数据开发,然后用SQL语句来创建一张关系表来存放我们之前计算出来的结果。 CREATE TABLE IF NOT EXISTS `uci_ecommerce_recommendation` ( `origin_product_name` string, `match_product_name` string, `coefficient` double ) ; 然后我们再使用如下的sql语句,将之前计算出来的结果转存储到这个表里面。 INSERT INTO uci_ecommerce_recommendation(origin_product_name, match_product_name, coefficient) SELECT foo.itemid as origin_product_name, split(foo.sim,':')[0] as match_product_name, split(foo.sim,':')[1] as coefficient FROM ( SELECT itemid, sim FROM pai_temp_82363_1078761_1 -- 这里写查看数据的时候的那个表名 lateral view explode(split(similarity,' ')) similarity AS sim ) foo 运行完毕之后,我们可以通过如下语句来检查是否成功插入数据 SELECT * FROM uci_ecommerce_recommendation ORDER BY coefficient DESC LIMIT 100 运行之后应该会看到如下结果: 完成之后,我们就可以开始配置我们的接口服务了。整个思路是我们会传入一个物品的名称,以及最相关的多少个商品数量N。首先我们去创建一个 Lightning 数据源,来查询我们这个MaxCompute中的数据。创建Lightning的方式可以参考这个 其中Lightning的 Endpoints 列表可以参考这里 创建完毕之后,我们就可以进入数据服务 然后我们以脚本模式创建接口。 创建完毕之后,我们点击左侧的API列表,进入这个服务。在选择表的时候 数据源类型选择为 Lightning,数据源名称就选择我们刚刚创建的。然后在下方的sql区域内写入 SELECT match_product_name, coefficient FROM uci_ecommerce_recommendation WHERE origin_product_name = ${origin_product_name} ORDER BY coefficient DESC LIMIT ${k} 然后点击右侧的请求参数,设置我们的请求参数类型。 配置完毕后,我们点击右上角的测试,输入一个物品的名字和多少个最相关的物品数量,就可以得到结果了 这样我们就低成本的完成了一个协同过滤系统从数据探索,集成,模型构建到接口的构建。整个流程花费还不到5块钱,有想法的同学也可以一起试试。同时也欢迎加钉钉群 23304116 和我们交流更多有关与阿里云大数据平台实战的想法。
第一期回顾现已开放: 【数据科学老司机在线教学第一期】人人用得起的机器学习平台——现场构建热狗识别模型 直播视频传送门文字版教程 第二期内容预告来袭! 人工智能千千万,没法落地都白干。 自从上次老司机用神经网络训练了热狗识别模型以后,群众们表示想看一波更加接地气,最好是那种能10分钟上手,一辈子受用的模型。 这次,我们就通过某著名电商公司的公开数据集,在阿里云大数据生态之下快速构建一个基于协同过滤的推荐系统! 为你揭开深夜剁手的惨案,重新成为万千少女的梦想(大雾)! 点下方链接直达传授现场,提前收藏,本周四(6月27日)敬请锁定: 【数据科学老司机在线教学第二期】阿里云大数据生态协同过滤推荐系统实战 主讲人:鱼哲,还是那位不愿意透露真实身份的产品经理 时间:2019 年 6月 27日 19:00 到 20:00 内容结构: 推荐系统简介 —— 15 分钟 基于Dataworks+PAI,手把手现场教学,教你快速构建一个基于协同过滤的推荐系统,甚至仅花5块钱即可运行(包含抽奖)—— 40 分钟 在线QA环节——10 分钟 重点提示,重点提示,重点提示,重要的事情说三遍: 直播期间会有各种好玩的互动,参与互动即有机会获得随机惊喜小礼品一件! 提前扫下方钉钉二维码或搜索群号 23304116 加入PAI用户交流群,即可在当天参与互动, 后续系列直播信息、有奖活动均会第一时间在群内告知! 同时还可随时咨(sao)询(rao)讲师相关问题,秒级响应速度为您服务~
前情提要 美剧《硅谷》大家想必都没怎么看过,大家可能都不知道人工智能识别热狗曾是硅谷最赚钱的技术之一。去年 HBO 发布了官方的 Not Hotdog 应用,支持 iOS 和 Android 平台,据说是用 TensorFlow、Keras 和 React Native 打造的,但是源码没有公开。 我们今天要做都就是这部美剧里面第四季里面让 杨建 成为百万富翁的模型:热狗识别模型。这一次,就让阿里云的数据科学老司机带你一起,利用机器学习pai平台训练自己的热狗识别模型,打破技术封锁。让你出任CEO,迎娶白富美/高富帅,走上人生巅峰。 Step 1: 开通PAI服务 工欲善其事,必先利其器。没有好的工具就想要训练出好的模型简直是天方夜谭。 这里就给大家简单的引导一下如何快速开通阿里云专属的机器学习平台PAI。点击进入这个链接之后,我们点击购买就可以了。 现在华东2上海地区的机器正在做活动,价格非常感人。有机会入手的同学可以考虑一下。 Step 2: 进入PAI控制台,创建你的DSW实例 开通服务之后,我们进入PAI的控制台,然后点击左侧的DSW-Notebook建模 进入DSW-Notebook建模之后,我们点击创建新实例。 这里计费方式选择我们购买时的计费方式,填写实例名称,最后写上资源配置。这一次实验我们暂时不会需要上传大型文件,所以我们可以暂时不设置存储资源配置。点击确定之后,我们就会看到一个实例正在创建中了。稍等几分钟,这个实例就会创建完成。然后我们点击 打开,就可以进入这个实例了。 进入之后我们就可以看到我们的DSW环境的样子了。 Step 3: 上传训练代码以及数据 我们先从这里下载我为各位精心准备好的代码和训练数据集压缩包。下载到本地之后,点击上传这个按钮 就可以把你的文件上传上来了。 上传成功后,我们打开Terminal 进入这个路径,然后输入 $ unzip ./not_hotdog.zip # 解压整个文件 $ cd not_hotdog.zip $ unzip seefood.zip # 解压训练数据集 然后就会看到我们的文件夹已经乖乖躺在我们的左侧的资源管理器里边儿了。 Step 4: 开始训练 接下来就是我们的硬核部分,我们直接把代码放上来。我们直接运行就可以拉 #!/usr/bin/env python # coding: utf-8 # # Import dependencies 导入依赖 # In[1]: import numpy as np import pandas as pd import os import tensorflow as tf rand_state = 42 # 顺便定义一个随机种子 tf.set_random_seed(rand_state) np.random.seed(rand_state) from skimage import exposure import cv2 import glob import time import matplotlib.pyplot as plt from keras.utils.vis_utils import plot_model # # 图像预处理的函数们 # In[2]: def rotateImage(img, angle): ''' img:三通道的图片 angle:随机角度 本功能是样本增强功能,对图片样本进行随机的旋转缩放 return:返回一个变换后的图片 ''' (rows, cols, ch) = img.shape # 得到源图片尺寸 #第一个参数旋转中心,第二个参数旋转角度,第三个参数:缩放比例 M = cv2.getRotationMatrix2D((cols/2,rows/2), angle, 1) return cv2.warpAffine(img, M, (cols,rows)) # 图像进行上面操作后生成的图像 def loadBlurImg(path, imgSize): ''' path:图片路径,字符串 imgsize:图片的尺寸,二元组,元素都是int ''' img = cv2.imread(path) # 读取图片数据 angle = np.random.randint(0, 360) # 生成0,360之间生成随机数,离散均匀随机,整形 img = rotateImage(img, angle) # 图片随机旋转,缩放 img = cv2.blur(img,(5,5)) # 每5*5的尺寸进行均值模糊 img = cv2.resize(img, imgSize) # 图片按照尺寸缩放 return img def loadImgClass(classPath, classLable, classSize, imgSize): ''' classPath:传入图片的路径,list集合 classLable:图片的类别,数值int classSize:样本数量 imgsize:图片的尺寸,二元组,元素都是int return:返回classSize个样本及标签 本函数从样本地址中生成classSize个数据,样本是经过旋转,缩放等变换的,图片规格是imgsize ''' x = [] y = [] for path in classPath: img = loadBlurImg(path, imgSize) # 加载地址中的图片并进行样本增强,生成imgsize大的图片 x.append(img) y.append(classLable) while len(x) < classSize: randIdx = np.random.randint(0, len(classPath)) img = loadBlurImg(classPath[randIdx], imgSize) x.append(img) y.append(classLable) return x, y def loadData(img_size, classSize, hotdogs, notHotdogs): ''' img_size:要返回图片的大小,int classSize:正例,负例样本数量,int hotsdogs,notHotdogs:正例,负例样本地址,都是个list return;返回训练样本及对应的标签 本函数读取数据并返回样本及标签 ''' imgSize = (img_size, img_size) # 要输入图片的尺寸 xHotdog, yHotdog = loadImgClass(hotdogs, 0, classSize, imgSize) # 生成正样本,classSize个 xNotHotdog, yNotHotdog = loadImgClass(notHotdogs, 1, classSize, imgSize) # 生成负样本,classSize个 print("There are", len(xHotdog), "hotdog images") print("There are", len(xNotHotdog), "not hotdog images") X = np.array(xHotdog + xNotHotdog) y = np.array(yHotdog + yNotHotdog) return X, y def toGray(images): ''' 样本灰度转换,生成后的图片是一个通道的 ''' # rgb2gray converts RGB values to grayscale values by forming a weighted sum of the R, G, and B components: # 0.2989 * R + 0.5870 * G + 0.1140 * B # source: https://www.mathworks.com/help/matlab/ref/rgb2gray.html images = 0.2989*images[:,:,:,0] + 0.5870*images[:,:,:,1] + 0.1140*images[:,:,:,2] return images def normalizeImages(images): ''' images:1个通道的图像 return:图像像素经过比例缩放,直方图均衡后的图像 ''' # use Histogram equalization to get a better range # source http://scikit-image.org/docs/dev/api/skimage.exposure.html#skimage.exposure.equalize_hist images = (images / 255.).astype(np.float32) # rgb像素是0-255之间,缩放至0-1的范围 for i in range(images.shape[0]): images[i] = exposure.equalize_hist(images[i]) # 直方图均衡之后的图像数组 images = images.reshape(images.shape + (1,)) # 二维扩成三维 return images def preprocessData(images): ''' images:三通道的image return:返回一通道,且数值经过比例缩放的图片(除以255,使之数值范围集中在0-1之间) ''' grayImages = toGray(images) return normalizeImages(grayImages) # # 我们需要对图像做一些骚操作 毕竟500张图片还是太少了 # In[3]: from keras.utils.np_utils import to_categorical from sklearn.model_selection import train_test_split size = 32 classSize = 20000 # In[7]: # 导入数据 hotdogs = glob.glob('./train/hot_dog/**/*.jpg', recursive=True) notHotdogs = glob.glob('./train/not_hot_dog/**/*.jpg', recursive=True) # In[12]: dd = (20000,20000) print(dd) # In[14]: # 骚操作一波 scaled_X, y = loadData(size, classSize, hotdogs, notHotdogs) scaled_X = preprocessData(scaled_X) # In[15]: y = to_categorical(y) # 目标变量独热 n_classes=2 print("y shape", y.shape) X_train, X_test, y_train, y_test = train_test_split( scaled_X, y, test_size=0.2, random_state=rand_state ) # 数据按照训练集0.8的比例分割 print("train shape X", X_train.shape) print("train shape y", y_train.shape) print("Test shape X:", X_test.shape) print("Test shape y: ", y_test.shape) inputShape = (size, size, 1) # In[8]: def plot_history(history): loss_list = [s for s in history.history.keys() if 'loss' in s and 'val' not in s] val_loss_list = [s for s in history.history.keys() if 'loss' in s and 'val' in s] acc_list = [s for s in history.history.keys() if 'acc' in s and 'val' not in s] val_acc_list = [s for s in history.history.keys() if 'acc' in s and 'val' in s] if len(loss_list) == 0: print('Loss is missing in history') return ## As loss always exists epochs = range(1,len(history.history[loss_list[0]]) + 1) ## Loss plt.figure(1) for l in loss_list: plt.plot(epochs, history.history[l], 'b', label='Training loss (' + str(str(format(history.history[l][-1],'.5f'))+')')) for l in val_loss_list: plt.plot(epochs, history.history[l], 'g', label='Validation loss (' + str(str(format(history.history[l][-1],'.5f'))+')')) plt.title('Loss') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() ## Accuracy plt.figure(2) for l in acc_list: plt.plot(epochs, history.history[l], 'b', label='Training accuracy (' + str(format(history.history[l][-1],'.5f'))+')') for l in val_acc_list: plt.plot(epochs, history.history[l], 'g', label='Validation accuracy (' + str(format(history.history[l][-1],'.5f'))+')') plt.title('Accuracy') plt.xlabel('Epochs') plt.ylabel('Accuracy') plt.legend() plt.show() # # 重点来了:构建模型就是这儿了 # In[9]: import keras from keras.models import Sequential from keras.callbacks import EarlyStopping, ModelCheckpoint from keras.layers import Conv2D, MaxPooling2D, Dense, Dropout, Flatten from keras.layers.normalization import BatchNormalization model = Sequential() model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', kernel_initializer='he_normal', input_shape=inputShape)) # 卷积 model.add(MaxPooling2D((2, 2))) # 池化 model.add(Dropout(0.25)) # 随机失活 model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Conv2D(128, (3, 3), activation='relu')) model.add(Dropout(0.4)) model.add(Flatten()) # 展成一维 model.add(Dense(128, activation='relu')) # 全连接 model.add(Dropout(0.3)) model.add(Dense(2, activation='softmax')) model.compile(loss=keras.losses.binary_crossentropy, optimizer=keras.optimizers.Adam(lr=1e-4), metrics=['accuracy']) start = time.time() model.summary() # Set callback functions to early stop training and save the best model so far callbacks = [ EarlyStopping( monitor='val_loss', patience=3 ), ModelCheckpoint( filepath='model.h5', monitor='val_acc', save_best_only=True ) ] history = model.fit( X_train, y_train, batch_size=32, epochs=100, callbacks=callbacks, verbose=0, validation_data=(X_test, y_test) ) end = time.time() print('Execution time: ', end-start) plot_history(history) 训练完成之后,我们可以简单的测试一下我们模型的准确率。下面这段代码就可以帮我们做到这一点。 hotdogs = glob.glob('./test/hot_dog/**/*.jpg', recursive=True) notHotdogs = glob.glob('./test/not_hot_dog/**/*.jpg', recursive=True) scaled_X_test, y_test = loadData(size, 250, hotdogs, notHotdogs) scaled_X_test = preprocessData(scaled_X_test) #get the predictions for the test data predicted_classes = model.predict_classes(scaled_X_test) # setup the true classes: just 250 hotdogs followed by 250 not hotdogs y_true = np.concatenate((np.zeros((250,)), np.ones((250,)))) from sklearn.metrics import classification_report print(classification_report(y_true, predicted_classes, target_names=['hotdog', 'not hotdog'])) 这样我们就可以看到我们模型的比较重要的一些评估结果了,比如准确率什么的。 Step 5: 测试模型 但是我们既然辛辛苦苦训练了,我们就要好好把玩一下这个模型。我们可以直接用下面这段代码来预测一个图片里面是不是有热狗。在这之前需要我们先创建一个名叫foo的文件夹,并把你想要测试的图片放进去 from PIL import Image import numpy as np from skimage import transform from IPython.display import Image as ipy_Image from IPython.display import display # 定义一个加载图片的函数,使我们的图片变成np array def load(filename): np_image = Image.open(filename) np_image = np.array(np_image).astype('float32')/255 np_image = transform.resize(np_image, (32, 32, 1)) np_image = np.expand_dims(np_image, axis=0) return np_image import os from os.path import join image_dir = './foo' os.listdir(image_dir) img_paths = [join(image_dir,filename) for filename in os.listdir(image_dir)] index_number = 0 image = load(img_paths[index_number]) score = model.predict(image) result = model.predict_classes(image) print(score[0][0], result) display(ipy_Image(img_paths[index_number])) 比如我们这里上传一张直播中网友们发来的图片,这张图片在直播的时候成功骗过了模型,得分最高 我们运行一下 就可以看到结果了 我们可以看到这个图片完美骗过了我们的模型,几乎达到了1。大家也可以拿这个模型测试一下自己身边长的像是热狗但是又不是热狗的东西,看看到底能得多少分~ 可以加钉钉群 23304116 来和群里的朋友们比拼你欺骗过模型的最高分(欺骗成功定义为不是热狗但是得分大于50)
看过美剧《硅谷》的同学都知道人工智能识别热狗曾是硅谷最赚钱的技术之一。 去年 HBO 发布了官方的 Not Hotdog 应用,支持 iOS 和 Android 平台,据说是用 TensorFlow、Keras 和 React Native 打造的,但是源码没有公开。 这一次,就让阿里云的数据科学老司机带你一起,利用机器学习pai平台训练自己的热狗识别模型,打破技术封锁。让你出任CEO,迎娶白富美/高富帅,走上人生巅峰。本次发车名额有限,先到先得~ 发车时间:2019 年 5月 30日 19:00 到 20:00发车地点:线上直播环境 https://tianchi.aliyun.com/course/live?&liveId=41006报名地址:https://survey.aliyun.com/apps/zhiliao/L-7_VDUqj
虽然已经 9102 年了MNIST手写数据集也早已经被各路神仙玩出了各种花样,比如其中比较秀的有用MINST训练手写日语字体的。但是目前还是很少有整体的将训练完之后的结果部署为一个可使用的服务的。大多数还是停留在最终Print出一个Accuracy。 这一次我们就借助阿里云的PAI平台来快速构建训练一个手写模型并且部署出一个生产可用级别的服务的教程让大家可以在其他的产品中调用这个服务作出更加有意思的项目。 整个部分会分为3篇文章分别对应机器学习中: 构建训练以及导出模型 模型的部署以及模型的调用。这篇文章里我们先讲讲如何构建训练并导出这个手写字体识别的模型。整个教程的代码基于Snapchat的ML大佬 Aymeric Damien 的Tensorflow 入门教程系列 Step 1: 下载代码 首先我们可以把代码Clone到本地或者直接Clone到DSW的实例。如何Clone到DSW实例的方法可以参考我的这篇文章。Clone完代码之后我们还需要准备训练所需要的数据集这边可以直接从Yann Lecun的网站下载。我这边然后我们可先运行一遍看一下效果。 我们可以看到代码Clone下来之后直接运行就已经帮我们训练出了model并且给出了现在这个Model的精度。在500个batch之后准确率达到了95%以上而且基于GPU的DSW实例训练这500个Batch只需要十几秒的时间。 Step 2: 修改部分代码使得可以自动导出SavedModel 这一步就是比较重要的地方了我们第一个需要关注的就是当前的这个Model里面的Input和Output. Input还比较清楚我们直接找所有placeholder就可以了 Output这一块就比较复杂了,在当前的model里我们可以看到output并不是直接定义的Y而是softmax之后的prediction 找到了这些之后就比较简单了。首先我们创建一个 Saver , 它可以帮助我们保存所有的tf变量以便之后导出模型使用 # 'Saver' op to save and restore all the variables saver = tf.train.Saver() 然后我们在模型训练的session结束的时候导出模型就好了。我们可以通过以下这段代码来导出我们训练好的模型 import datetime # 声明导出模型路径这边加入了时间作为路径名 这样每次训练的时候就可以保存多个版本的模型了 export_path = "./model-" + datetime.datetime.now().strftime('%Y-%m-%d_%H:%M:%S') # 保存训练的日志文件方便如果出问题了我们可以用 tensorboard 来可视化神经网络排查问题 tf.summary.FileWriter('./graph-' + datetime.datetime.now().strftime('%Y-%m-%d_%H:%M:%S') , sess.graph) # 构建我们的Builder builder = tf.saved_model.builder.SavedModelBuilder(export_path) # 声明各种输入这里有一个X和一个keep_prob作为输入然后 tensor_info_x = tf.saved_model.utils.build_tensor_info(X) tensor_info_keep_prob = tf.saved_model.utils.build_tensor_info(keep_prob) tensor_info_y = tf.saved_model.utils.build_tensor_info(prediction) prediction_signature = ( tf.saved_model.signature_def_utils.build_signature_def( # 声明输入 inputs={ 'images': tensor_info_x, 'keep_prob' : tensor_info_keep_prob }, # 声明输出 outputs={ 'scores': tensor_info_y }, method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME ) ) legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op') builder.add_meta_graph_and_variables( sess, [tf.saved_model.tag_constants.SERVING], signature_def_map={ 'predict_images': prediction_signature, }, legacy_init_op=legacy_init_op) # 保存模型 builder.save() 我们可以吧这段代码插在这里这样训练完成的时候就会自动导出了 导出之后应该会有如下的文件结构我们也可以在左边的文件管理器中查看 ./model-2019-05-20_13:50:26 ├── saved_model.pb └── variables ├── variables.data-00000-of-00001 └── variables.index 1 directory, 3 files Step 3: 部署我们的模型 终于到了可以部署的阶段了。但是在部署之前先别那么着急建议用 tensorboard 把训练日志下载到本地之后看一下。这一步除了可以可视化的解释我们的模型之外还可以帮助我们理清我们的模型的输入和输出分别是什么。这边我先在有日志文件的路径打开一个tensorboard 通过这个命令 tensorboard --logdir ./ 然后我们在游览器里输入默认地址 localhost:6006 就可以看到了 从这个图里也可以看到我们的这个Model里有2个输入源分别叫做images和keep_prob。并且点击它们之后我们还能看到对应的数据格式应该是什么样的。不过没有办法使用 Tensorboard 的同学也不用担心因为EAS这个产品也为我们提供了构造请求的方式。这一次部署我们先使用WEB界面来部署我们的服务这一步也可以通过EASCMD来实现之后我会再写一篇如何用好EASCMD的文章。 我们可以吧模型文件下载完之后用zip打包然后到PAI产品的控制台点击EAS-模型在线服务.ZIP打包可以用这个命令如果你是Unix的用户的话 zip -r model.zip path/to/model_files 进入EAS之后我们点击模型部署上传 然后继续配置我们的processor这一次因为我们是用tensorflow训练的所以选择Tensorflow然后资源选择CPU有需要的同学可以考虑GPU然后上传我们的模型文件. 点击下一步我们选新建服务然后给我们的服务起个名字,并且配置资源数量。 然后最后确认一下就可以点击部署了 Step 4: 调试我们的模型 回到EAS的控制台我们可以看到我们的服务正在被构建中。等到状态显示Running的时候我们就可以开始调试了。我们可以先点击在线调试 会让我们跳转到一个Debug 接口的页面。什么都不需要填直接点击提交我们就可以看到服务的数据格式了 然后我们用一段python2的代码来调试这个刚刚部署完的服务。python3的SDK暂时还在研发中。注意要把下面的app_key, app_secret, url 换成我们刚刚部署好的内容。点击模型名字就可以看见了。 其中测试图片的数据大家可以在这下载到 #!/usr/bin/env python # -*- coding: utf-8 -*- import json from urlparse import urlparse from com.aliyun.api.gateway.sdk import client from com.aliyun.api.gateway.sdk.http import request from com.aliyun.api.gateway.sdk.common import constant from pai_tf_predict_proto import tf_predict_pb2 import cv2 import numpy as np with open('9.jpg', 'rb') as infile: buf = infile.read() # 使用numpy将字节流转换成array x = np.fromstring(buf, dtype='uint8') # 将读取到的array进行图片解码获得28 × 28的矩阵 img = cv2.imdecode(x, cv2.IMREAD_UNCHANGED) # 由于预测服务API需要长度为784的一维向量将矩阵reshape成784 img = np.reshape(img, 784) def predict(url, app_key, app_secret, request_data): cli = client.DefaultClient(app_key=app_key, app_secret=app_secret) body = request_data url_ele = urlparse(url) host = 'http://' + url_ele.hostname path = url_ele.path req_post = request.Request(host=host, protocol=constant.HTTP, url=path, method="POST", time_out=6000) req_post.set_body(body) req_post.set_content_type(constant.CONTENT_TYPE_STREAM) stat,header, content = cli.execute(req_post) return stat, dict(header) if header is not None else {}, content def demo(): # 输入模型信息,点击模型名字就可以获取到了 app_key = 'YOUR_APP_KEY' app_secret = 'YOUR_APP_SECRET' url = 'YOUR_APP_URL' # 构造服务 request = tf_predict_pb2.PredictRequest() request.signature_name = 'predict_images' request.inputs['images'].dtype = tf_predict_pb2.DT_FLOAT # images 参数类型 request.inputs['images'].array_shape.dim.extend([1, 784]) # images参数的形状 request.inputs['images'].float_val.extend(img) # 数据 request.inputs['keep_prob'].dtype = tf_predict_pb2.DT_FLOAT # keep_prob 参数的类型 request.inputs['keep_prob'].float_val.extend([0.75]) # 默认填写一个 # å°†pbåºåˆ—化æˆstringè¿›è¡Œä¼ è¾“ request_data = request.SerializeToString() stat, header, content = predict(url, app_key, app_secret, request_data) if stat != 200: print 'Http status code: ', stat print 'Error msg in header: ', header['x-ca-error-message'] if 'x-ca-error-message' in header else '' print 'Error msg in body: ', content else: response = tf_predict_pb2.PredictResponse() response.ParseFromString(content) print(response) if __name__ == '__main__': demo() 运行这个python代码然后我们会得到 outputs { key: "scores" value { dtype: DT_FLOAT array_shape { dim: 1 dim: 10 } float_val: 0.0 float_val: 0.0 float_val: 0.0 float_val: 0.0 float_val: 0.0 float_val: 0.0 float_val: 0.0 float_val: 0.0 float_val: 0.0 float_val: 1.0 } } 我们可以看到从0开始数的最后一个也就是第9个的结果是1 其他都是0 说明我们的结果是9和我们输入的一样。这样我们就简单轻松的构建了一个在线服务能够将用户的图片中手写数字识别出来。配合其他Web框架或者更多的东西我们就可以作出更好玩的玩具啦
在学习数据科学的时候,我们往往需要从各个地方下载各种各样的数据集和代码。其中大名鼎鼎的就是我们的Github。这篇文章会简单讲讲我们如何从Github下载想要的学习资源,然后在DSW上进行运行和学习。 Step 0: 购买华东2地区的PAI-DSW 记得要先购买。 购买地址 现在只有华东2地区的资源可以访问github Step 1: 选择华东2地区的PAI-DSW P100 系列 这边 一定 要选择P100系列的,这个系列最近有很多活动 而且也只有华东2地区的p100系列可以访问github Step 2: 打开PAI实例 然后我们通过控制台打开我们的PAI-DSW实验室 Step 3: 创建Terminal 滑动DSW Launcher到底部,单击Terminal启动一个命令行的Session Step 4: 输入想要下载的仓库的命令 这里就和平时我们从github上面clone东西一样,通过输入 git clone https://github.com/jakevdp/PythonDataScienceHandbook.git 并运行就可以下载了。我这边以数据科学方向大牛 Jake Vanderplas 的一本 数据科学基本法 为例,将这本书下载到DSW中去。 Step 5: 打开刚刚下载的文件夹,开始阅读数据科学基本法 文件下载完成之后,在左边就能看到了。要注意下载的路径,不要下载了之后找不到就尴尬了 以上就是一个简单的通过PAI下载Github上代码仓的教程,欢迎大家私聊我更多资源~ PAI 地址:https://data.aliyun.com/product/learn
2019年07月
2019年06月