数据专栏

智能大数据搬运工,你想要的我们都有

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

「深度学习福利」大神带你进阶工程师,立即查看>>>
3月21日,北京国家会议中心,阿里云北京峰会吸引了全球计算机行业的目光。十年时间,阿里云开创中国云时代,研发了属于自己的云操作系统和城市AI平台,云普惠各行各业数百万客户。下一个十年,在阿里云战略升级为阿里云智能之时,它又将带给各行各业什么样的变化?
阿里云MVP北京闭门会现场座无虚席
这个答案,在翌日举行的阿里云MVP北京闭门会上呼之欲出。在过去的数百个日子里,从传统制造业到新零售,从人工智能到新金融,阿里云MVP正在成为中国乃至全球各行各业数字化转型的中坚力量。当这群技术先锋者与阿里核心技术力量汇聚在一起,一场无与伦比的思想碰撞就此展开。
阿里云MVP荣聚北京 共话未来发展趋势
阿里云MVP(阿里云最有价值专家),是专注于帮助他人充分了解和使用阿里云的技术实践领袖。截至目前,MVP大家庭的成员已近500位,来自全球27个国家和地区。他们如繁星一般,遍布在各行各业:人工智能、云计算、大数据、区块链、安全等不一而足。在当天活动现场,阿里云MVP围绕着“未来的大趋势是红灯还是绿灯”的话题展开了精彩的讨论。

阿里云MVP正在围绕“红灯与绿灯”展开热烈的讨论
在制造业从事工艺、质量管理等工作20年,如今扎根制造业升级改造的韩俊仙老师表示:“红灯、绿灯交替,才能有戏。作为新经济技术模式的探索者,我们要和优秀者为伍,跟着正在发展的企业一起来升级,在阿里云的黑土地上播种扎根,生命力才会更长久。”这一番发言赢得了现场热烈的掌声。
冬天来了,春天还会远吗?退一万步说,即使凛冬将至,生存下来的公司一定拥有更强的生命力。可是如何活得更久、更强?闭门会当天集结了由阿里云核心技术人、阿里云MVP组成的超豪华嘉宾阵容,共同为参会者准备了数把破阵的“利剑”。
重磅嘉宾倾囊相授 助力开发者破阵蜕变
重磅嘉宾悉数亮相
阿里云智能战略与合作部总经理刘湘雯带来了对开发者的寄语与希冀,表示希望和MVP共同探索属于每个领域独一无二的道路;阿里云智能计算平台事业部研究员林伟分享了机器学习平台PAI3.0版本,帮助大幅度降低人工智能门槛和开发成本;VIPKID高级副总裁项碧波带来“在线教育的核心竞争力”的秘籍攻略;杭州博拉科技CEO周公爽,细数工业互联网的现状与痛点;钉钉资深专家剑翘更深度揭秘众所期待的钉钉开发平台,让企业、服务商、开发者紧密联系在一起,数字化的工作方式吸引了台下大批管理者。最后登场的是阿里云MVP项目负责人欧阳庆,宣布阿里云MVP北方片区联合会成立,现场举手报名的人数近半数。未来联合会将会成为MVP学习交流、资源共享的重要平台。
梅一多博士是新晋的第八期MVP成员之一,也是第一次参加MVP闭门会。这位来自西安交通大学的计算机博士,深耕云计算领域多年,对当天的活动赞不绝口:“学界的研究更多地是纯粹的追求技术创新,但来自业界的信息输入不足。这次交流会中,不管是阿里云MVP还是阿里技术专家所提供的业界信息,都是非常宝贵的,这是我们从业者与整个业界、阿里云非常难得的一种链接形式。”
十年携手再出发 共同加速行业升级
从云栖大会、闭门会、MVP Techshow的技术布道到支教、养老、幼儿园的码上公益项目、专业尽责的产品体验官,MVP们一起走过玄奘之路的荒漠草原,也一起用技术扶贫济困、温暖人心。阿里云MVP至今已完成数千次线上线下贡献,其中于湖畔大学隆重举行的 2018 MVP全球闭门会、多元化交流学习平台的 MVP学院更是赢得了业界的高度关注与赞誉。
阿里云MVP北京闭门会参会者合影
随着“阿里云”成为“阿里巴巴经济体的技术底座”和“阿里巴巴所有技术和产品的输出平台”,阿里云战略加速的“四级火箭”已全火力开启。阿里云MVP将参与到利用研发和应用云智能技术来改变各行各业的历史征程中。在这里,阿里云将成为解决方案的重要组成部分,助力数据、智能与客户需求真正产生化学反应,技术在实践中突破创新,在实践中成长演化,在实践中落地生根,生生不息。
"十年再出发”,未来的绿灯已一路点亮。这是一个美好的时代,也必将是一个伟大的时代。期待您加入阿里云MVP,我们共同乘上云智能的“四级火箭”,加速行业升级。
大咖精彩观点合集:



阿里云MVP官网:
https://mvp.aliyun.com/
作者:helloworld01
原文链接
本文为云栖社区原创内容,未经允许不得转载。
人工智能
2019-03-27 12:22:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
由于部署需要,测试用的dlib 人脸工具k开发环境需要部署到docker环境中,记录下安装过程。
安装dlib前,首先安装如下软件,cmake和boost
1、安装cmake
下载安装包:官网地址:https://cmake.org/download/
历史版本地址:https://cmake.org/files/dev/?C=M;O=D
解压安装包:tar -zxvf cmake-3.11.20180604-g96958.tar.gz
编译和安装:cmake-3.11.20180604-g96958
./bootstrap
make & make install
加入系统:ln -s /usr/cmake-3.11.20180604-g96958/bin/* /usr/bin/
验证:cmake --version
异常:安装过程报错,提示缺失缺少c++11环境时,安装c++11环境
解决方式:yum install gcc gcc-c++
2、安装Boost
下载安装包:wget https://dl.bintray.com/boostorg/release/1.64.0/source/boost_1_64_0.tar.gz
解压:tar zxvf boost_1_64_0.tar.gz
编译:cd boost_1_64_0/
出现入下内容表示成功:

./bootstrap.sh --with-libraries=all --with-toolset=gcc
./b2 toolset=gcc 时间比较久
安装:./b2 install --prefix=/usr
确认是否安装成功:find / -name libboost_random
3、安装dlib
下载:http://dlib.net/ml.html

解压安装包:tar -jxvf dlib-19.17.tar.bz2
安装:cd dlib-19.17
python3 setup.py install 如果系统的python3版本调用为python,使用python。我的机器装了Python2和Python3,python命令为Python2
测试:
python3
import dlib 不报错,说明安装成功
参考博客:
https://blog.csdn.net/whjay520/article/details/80841253
人工智能
2019-03-26 14:54:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
此程序基于 虹软人脸识别进行的开发 前提条件从虹软官网下载获取ArcFace引擎应用开发包,及其对应的激活码(App_id, SDK_key) 将获取到的开发包导入到您的应用中 App_id与SDK_key是在初始化的时候需要使用基本类型所有基本类型在平台库中有定义。 定义规则是在ANSIC 中的基本类型前加上字母“M”同时将类型的第一个字母改成大写。例如“long” 被定义成“MLong”数据结构与枚举 AFR_FSDK_FACEINPUT 描述: 脸部信息 定义 typedef struct{ MRECT rcFace; AFR_FSDK_OrientCode lOrient; } AFR_FSDK_FACEINPUT, *LPAFR_FSDK_FACEINPUT; 成员描述 rcFace脸部矩形框信息 lOrient脸部旋转角度 AFR_FSDK_FACEMODEL 描述: 脸部特征信息 定义 typedef struct{ MByte *pbFeature; MInt32 lFeatureSize; } AFR_FSDK_FACEMODEL, *LPAFR_FSDK_FACEMODEL; 成员描述 pbFeature提取到的脸部特征 lFeatureSize特征信息长度 AFR_FSDK_VERSION 描述: 引擎版本信息 定义 typedef struct{ MInt32 lCodebase; MInt32 lMajor; MInt32 lMinor; MInt32 lBuild; MInt32 lFeatureLevel; MPChar Version; MPChar BuildDate; MPChar CopyRight; } AFR_FSDK_VERSION, *LPAFR_FSDK_VERSION; 成员描述 lCodebase代码库版本号 lMajor主版本号 lMinor次版本号 lBuild编译版本号,递增 lFeatureLevel特征库版本号 Version字符串形式的版本号 BuildDate编译时间 CopyRight版权 枚举AFR_FSDK_ORIENTCODE 描述: 基于逆时针的脸部方向枚举值 定义 enum AFR_FSDK_ORIENTCODE{ AFR_FSDK_FOC_0 = 0x1, AFR_FSDK_FOC_90 = 0x2, AFR_FSDK_FOC_270 = 0x3, AFR_FSDK_FOC_180 = 0x4, AFR_FSDK_FOC_30 = 0x5, AFR_FSDK_FOC_60 = 0x6, AFR_FSDK_FOC_120 = 0x7, AFR_FSDK_FOC_150 = 0x8, AFR_FSDK_FOC_210 = 0x9, AFR_FSDK_FOC_240 = 0xa, AFR_FSDK_FOC_300 = 0xb, AFR_FSDK_FOC_330 = 0xc }; 成员描述 AFR_FSDK_FOC_00 度 AFR_FSDK_FOC_9090度 AFR_FSDK_FOC_270270度 AFR_FSDK_FOC_180180度 AFR_FSDK_FOC_3030度 AFR_FSDK_FOC_6060度 AFR_FSDK_FOC_120120度 AFR_FSDK_FOC_150150度 AFR_FSDK_FOC_210210度 AFR_FSDK_FOC_240240度 AFR_FSDK_FOC_300300度 AFR_FSDK_FOC_330330度
支持的颜色格式 描述: 颜色格式及其对齐规则 定义 ASVL_PAF_I420 8-bit Y层,之后是8-bit的2x2 采样的U层和V层 ASVL_PAF_YUYV Y0, U0, Y1, V0 ASVL_PAF_RGB24_B8G8R8 BGR24, B8G8R8 API ReferenceAFR_FSDK_InitialEngine 描述: 初始化引擎参数 原型 MRESULT AFR_FSDK_InitialEngine( MPChar AppId, MPChar SDKKey, Mbyte *pMem, MInt32 lMemSize, MHandle *phEngine ); 参数 AppId[in] 用户申请SDK时获取的App Id SDKKey[in] 用户申请SDK时获取的SDK Key pMem[in] 分配给引擎使用的内存地址 lMemSize[in] 分配给引擎使用的内存大小 phEngine[out] 引擎handle 返回值: 成功返回MOK,否则返回失败code。失败codes如下所列: MERR_INVALID_PARAM 参数输入非法 MERR_NO_MEMORY 内存不足AFR_FSDK_ExtractFRFeature 描述: 获取脸部特征参数 原型 MRESULT AFR_FSDK_ExtractFRFeature ( MHandle hEngine, LPASVLOFFSCREEN pInputImage, LPAFR_FSDK_FACEINPUT pFaceRes, LPAFR_FSDK_FACEMODEL pFaceModels ); 参数 hEngine[in] 引擎handle pInputImage[in] 输入的图像数据 pFaceRes[in] 已检测到的脸部信息 pFaceModels[out] 提取的脸部特征信息 返回值: 成功返回MOK,否则返回失败code。失败codes如下所列: MERR_INVALID_PARAM 参数输入非法 MERR_NO_MEMORY 内存不足AFR_FSDK_FacePairMatching 描述: 脸部特征比较 原型 MRESULT AFR_FSDK_FacePairMatching( MHandle hEngine, AFR_FSDK_FACEMODEL *reffeature, AFR_FSDK_FACEMODEL *probefeature, MFloat *pfSimilScore ); 参数 hEngine[in] 引擎handle reffeature[in] 已有脸部特征信息 probefeature[in] 被比较的脸部特征信息 pfSimilScore[out] 脸部特征相似程度数值 返回值: 成功返回MOK,否则返回失败code。失败codes如下所列: MERR_INVALID_PARAM 参数输入非法 MERR_NO_MEMORY 内存不足 AFR_FSDK_UninitialEngine 描述: 销毁引擎,释放相应资源 原型 MRESULT AFR_FSDK_UninitialEngine( MHandle hEngine ); 参数 hEngine[in] 引擎handle 返回值: 成功返回MOK,否则返回失败code。失败codes如下所列: MERR_INVALID_PARAM 参数输入非法 AFR_FSDK_GetVersion 描述: 获取SDK版本信息参数 原型 const AFR_FSDK_VERSION * AFR_FSDK_GetVersion( MHandle hEngine ); 相关事例代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ArcsoftFace { public struct AFD_FSDK_FACERES { public int nFace; // number of faces detected public IntPtr rcFace; // The bounding box of face public IntPtr lfaceOrient; // the angle of each face } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ArcsoftFace { public struct AFR_FSDK_FACEINPUT { public MRECT rcFace; // The bounding box of face public int lfaceOrient; // The orientation of face } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ArcsoftFace { public struct AFR_FSDK_FACEMODEL { public IntPtr pbFeature; // The extracted features public int lFeatureSize; // The size of pbFeature } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ArcsoftFace { public struct AFR_FSDK_Version { public int lCodebase; public int lMajor; public int lMinor; public int lBuild; public int lFeatureLevel; public IntPtr Version; public IntPtr BuildDate; public IntPtr CopyRight; } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace ArcsoftFace { public class AmFaceVerify { /** * 初始化人脸检测引擎 * @return 初始化人脸检测引擎 */ [DllImport("libarcsoft_fsdk_face_detection.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int AFD_FSDK_InitialFaceEngine(string appId, string sdkKey, IntPtr pMem, int lMemSize, ref IntPtr pEngine, int iOrientPriority, int nScale, int nMaxFaceNum); /** * 获取人脸检测 SDK 版本信息 * @return 获取人脸检测SDK 版本信息 */ [DllImport("libarcsoft_fsdk_face_detection.dll", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr AFD_FSDK_GetVersion(IntPtr pEngine); /** * 根据输入的图像检测出人脸位置,一般用于静态图像检测 * @return 人脸位置 */ [DllImport("libarcsoft_fsdk_face_detection.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int AFD_FSDK_StillImageFaceDetection(IntPtr pEngine, IntPtr offline, ref IntPtr faceRes); /** * 初始化人脸识别引擎 * @return 初始化人脸识别引擎 */ [DllImport("libarcsoft_fsdk_face_recognition.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int AFR_FSDK_InitialEngine(string appId, string sdkKey, IntPtr pMem, int lMemSize, ref IntPtr pEngine); /** * 获取人脸识别SDK 版本信息 * @return 获取人脸识别SDK 版本信息 */ [DllImport("libarcsoft_fsdk_face_recognition.dll", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr AFR_FSDK_GetVersion(IntPtr pEngine); /** * 提取人脸特征 * @return 提取人脸特征 */ [DllImport("libarcsoft_fsdk_face_recognition.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int AFR_FSDK_ExtractFRFeature(IntPtr pEngine, IntPtr offline, IntPtr faceResult, IntPtr localFaceModels); /** * 获取相似度 * @return 获取相似度 */ [DllImport("libarcsoft_fsdk_face_recognition.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int AFR_FSDK_FacePairMatching(IntPtr pEngine, IntPtr faceModels1, IntPtr faceModels2, ref float fSimilScore); #region delete ///** // * 创建人脸检测引擎 // * @param [in] model_path 模型文件夹路径 // * @param [out] engine 创建的人脸检测引擎 // * @return =0 表示成功,<0 表示错误码。 // */ //[DllImport("AmFaceDet.dll", CallingConvention = CallingConvention.Cdecl)] //public static extern int AmCreateFaceDetectEngine(string modelPath, ref IntPtr faceDetectEngine); ///** // * 创建人脸识别引擎 // * @param [in] model_path 模型文件夹路径 // * @param [out] engine 创建的人脸识别引擎 // * @return =0 表示成功,<0 表示错误码。 // */ //[DllImport("AmFaceRec.dll", CallingConvention = CallingConvention.Cdecl)] //public static extern int AmCreateFaceRecogniseEngine(string modelPath, ref IntPtr facRecogniseeEngine); ///** // * 创建人脸比对别引擎 // * @param [in] model_path 模型文件夹路径 // * @param [out] engine 创建的人脸比对引擎 // * @return =0 表示成功,<0 表示错误码。 // */ //[DllImport("AmFaceCompare.dll", CallingConvention = CallingConvention.Cdecl)] //public static extern int AmCreateFaceCompareEngine(ref IntPtr facCompareEngine); ///** // * 设置人脸引擎参数 // * @param [in] engine 人脸引擎 // * @param [in] param 人脸参数 // */ //[DllImport("AmFaceDet.dll", CallingConvention = CallingConvention.Cdecl)] //public static extern void AmSetParam(IntPtr faceDetectEngine, [MarshalAs(UnmanagedType.LPArray)] [In] TFaceParams[] setFaceParams); ///** // * 人脸检测 // * @param [in] engine 人脸引擎 // * @param [in] bgr 图像数据,BGR格式 // * @param [in] width 图像宽度 // * @param [in] height 图像高度 // * @param [in] pitch 图像数据行字节数 // * @param [in,out] faces 人脸结构体数组,元素个数应等于期望检测人脸个数 // * @param [in] face_count 期望检测人脸个数 // * @return >=0 表示实际检测到的人脸数量,<0 表示错误码。 // */ //[DllImport("AmFaceDet.dll", CallingConvention = CallingConvention.Cdecl)] //public static extern int AmDetectFaces(IntPtr faceDetectEngine, [MarshalAs(UnmanagedType.LPArray)] [In] byte[] image, int width, int height, int pitch, [MarshalAs(UnmanagedType.LPArray)] [In][Out] TAmFace[] faces, int face_count); ///** // * 抽取人脸特征 // * @param [in] engine 人脸引擎 // * @param [in] bgr 图像数据,BGR格式 // * @param [in] width 图像宽度 // * @param [in] height 图像高度 // * @param [in] pitch 图像数据行字节数 // * @param [in] face 人脸结构体 // * @param [out] feature 人脸特征 // * @return =0 表示成功,<0 表示错误码。 // */ //[DllImport("AmFaceRec.dll", CallingConvention = CallingConvention.Cdecl)] ////public static extern int AmExtractFeature(IntPtr faceEngine, [MarshalAs(UnmanagedType.LPArray)] [In] byte[] image, int width, int height, int pitch, [MarshalAs(UnmanagedType.LPArray)] [In] TAmFace[] faces, ref byte[] feature); //public static extern int AmExtractFeature(IntPtr facRecogniseeEngine, [MarshalAs(UnmanagedType.LPArray)] [In] byte[] image, int width, int height, int pitch, [MarshalAs(UnmanagedType.LPArray)] [In] TAmFace[] faces, [MarshalAs(UnmanagedType.LPArray)] [Out] byte[] feature); ///** // * 比对两个人脸特征相似度 // * @param [in] engine 人脸引擎 // * @param [in] feature1 人脸特征1 // * @param [in] feature2 人脸特征2 // * @return 人脸相似度 // */ //[DllImport("AmFaceCompare.dll", CallingConvention = CallingConvention.Cdecl)] //public static extern float AmCompare(IntPtr facCompareEngine, byte[] feature1, byte[] feature2); #endregion } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace ArcsoftFace { public struct ASVLOFFSCREEN { public int u32PixelArrayFormat; public int i32Width; public int i32Height; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public IntPtr[] ppu8Plane; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public int[] pi32Pitch; } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ArcsoftFace { public struct MRECT { public int left; public int top; public int right; public int bottom; } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Drawing.Imaging; using System.Diagnostics; using System.Threading; using ArcsoftFace; namespace ArcsoftFace { public partial class Form1 : Form { byte[] firstFeature; byte[] secondFeature; //人脸检测引擎 IntPtr detectEngine = IntPtr.Zero; //人脸识别引擎 IntPtr regcognizeEngine = IntPtr.Zero; //拖拽线程 private Thread threadMultiExec; //构造函数 public Form1() { InitializeComponent(); } //把图片转成byte[] private byte[] getBGR(Bitmap image, ref int width, ref int height, ref int pitch) { //Bitmap image = new Bitmap(imgPath); const PixelFormat PixelFormat = PixelFormat.Format24bppRgb; BitmapData data = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, PixelFormat); IntPtr ptr = data.Scan0; int ptr_len = data.Height * Math.Abs(data.Stride); byte[] ptr_bgr = new byte[ptr_len]; Marshal.Copy(ptr, ptr_bgr, 0, ptr_len); width = data.Width; height = data.Height; pitch = Math.Abs(data.Stride); int line = width * 3; int bgr_len = line * height; byte[] bgr = new byte[bgr_len]; for (int i = 0; i < height; ++i) { Array.Copy(ptr_bgr, i * pitch, bgr, i * line, line); } pitch = line; image.UnlockBits(data); return bgr; } //选择第一张照片 private void button4_Click(object sender, EventArgs e) { OpenFileDialog openFile = new OpenFileDialog(); openFile.Filter = "图片文件|*.bmp;*.jpg;*.jpeg;*.png|所有文件|*.*;"; openFile.Multiselect = false; openFile.FileName = ""; if (openFile.ShowDialog() == DialogResult.OK) { this.pictureBox1.Image = null; Image image = Image.FromFile(openFile.FileName); this.pictureBox1.Image = new Bitmap(image); image.Dispose(); firstFeature = detectAndExtractFeature(this.pictureBox1.Image, 1); } } //选择第二张照片 private void button2_Click(object sender, EventArgs e) { OpenFileDialog openFile = new OpenFileDialog(); openFile.Filter = "图片文件|*.bmp;*.jpg;*.jpeg;*.png|所有文件|*.*;"; openFile.Multiselect = false; openFile.FileName = ""; if (openFile.ShowDialog() == DialogResult.OK) { this.pictureBox2.Image = null; Image image = Image.FromFile(openFile.FileName); this.pictureBox2.Image = new Bitmap(image); image.Dispose(); secondFeature = detectAndExtractFeature(this.pictureBox2.Image, 2); } } //提取识别出的人脸 public static Bitmap CutFace(Bitmap srcImage, int StartX, int StartY, int iWidth, int iHeight) { if (srcImage == null) { return null; } int w = srcImage.Width; int h = srcImage.Height; if (StartX >= w || StartY >= h) { return null; } if (StartX + iWidth > w) { iWidth = w - StartX; } if (StartY + iHeight > h) { iHeight = h - StartY; } try { Bitmap bmpOut = new Bitmap(iWidth, iHeight, PixelFormat.Format24bppRgb); Graphics g = Graphics.FromImage(bmpOut); g.DrawImage(srcImage, new Rectangle(0, 0, iWidth, iHeight), new Rectangle(StartX, StartY, iWidth, iHeight), GraphicsUnit.Pixel); g.Dispose(); return bmpOut; } catch { return null; } } //获取相似度 private void button3_Click(object sender, EventArgs e) { float similar = 0f; AFR_FSDK_FACEMODEL localFaceModels = new AFR_FSDK_FACEMODEL(); IntPtr firstFeaturePtr = Marshal.AllocHGlobal(firstFeature.Length); Marshal.Copy(firstFeature, 0, firstFeaturePtr, firstFeature.Length); localFaceModels.lFeatureSize = firstFeature.Length; localFaceModels.pbFeature = firstFeaturePtr; IntPtr secondFeaturePtr = Marshal.AllocHGlobal(secondFeature.Length); Marshal.Copy(secondFeature, 0, secondFeaturePtr, secondFeature.Length); AFR_FSDK_FACEMODEL localFaceModels2 = new AFR_FSDK_FACEMODEL(); localFaceModels2.lFeatureSize = secondFeature.Length; localFaceModels2.pbFeature = secondFeaturePtr; IntPtr firstPtr = Marshal.AllocHGlobal(Marshal.SizeOf(localFaceModels)); Marshal.StructureToPtr(localFaceModels, firstPtr, false); IntPtr secondPtr = Marshal.AllocHGlobal(Marshal.SizeOf(localFaceModels2)); Marshal.StructureToPtr(localFaceModels2, secondPtr, false); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); int result = AmFaceVerify.AFR_FSDK_FacePairMatching(regcognizeEngine, firstPtr, secondPtr, ref similar); stopwatch.Stop(); setControlText(this.label1, "相似度:" + similar.ToString() + " 耗时:" + stopwatch.ElapsedMilliseconds.ToString() + "ms"); //this.label1.Text = "相似度:" + similar.ToString() + " 耗时:" + stopwatch.ElapsedMilliseconds.ToString() + "ms"; localFaceModels = new AFR_FSDK_FACEMODEL(); Marshal.FreeHGlobal(firstFeaturePtr); Marshal.FreeHGlobal(secondFeaturePtr); Marshal.FreeHGlobal(firstPtr); Marshal.FreeHGlobal(secondPtr); localFaceModels2 = new AFR_FSDK_FACEMODEL(); } //检测人脸、提取特征 private byte[] detectAndExtractFeature(Image imageParam, int firstSecondFlg) { byte[] feature = null; try { Console.WriteLine(); Console.WriteLine("############### Face Detect Start #########################"); int width = 0; int height = 0; int pitch = 0; Bitmap bitmap = new Bitmap(imageParam); byte[] imageData = getBGR(bitmap, ref width, ref height, ref pitch); //GCHandle hObject = GCHandle.Alloc(imageData, GCHandleType.Pinned); //IntPtr imageDataPtr = hObject.AddrOfPinnedObject(); IntPtr imageDataPtr = Marshal.AllocHGlobal(imageData.Length); Marshal.Copy(imageData, 0, imageDataPtr, imageData.Length); ASVLOFFSCREEN offInput = new ASVLOFFSCREEN(); offInput.u32PixelArrayFormat = 513; offInput.ppu8Plane = new IntPtr[4]; offInput.ppu8Plane[0] = imageDataPtr; offInput.i32Width = width; offInput.i32Height = height; offInput.pi32Pitch = new int[4]; offInput.pi32Pitch[0] = pitch; AFD_FSDK_FACERES faceRes = new AFD_FSDK_FACERES(); IntPtr offInputPtr = Marshal.AllocHGlobal(Marshal.SizeOf(offInput)); Marshal.StructureToPtr(offInput, offInputPtr, false); IntPtr faceResPtr = Marshal.AllocHGlobal(Marshal.SizeOf(faceRes)); //Marshal.StructureToPtr(faceRes, faceResPtr, false); Console.WriteLine("StartTime:{0}", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ffff")); Stopwatch watchTime = new Stopwatch(); watchTime.Start(); //人脸检测 int detectResult = AmFaceVerify.AFD_FSDK_StillImageFaceDetection(detectEngine, offInputPtr, ref faceResPtr); watchTime.Stop(); if (firstSecondFlg == 1) { setControlText(this.label5, String.Format("检测耗时:{0}ms", watchTime.ElapsedMilliseconds)); //this.label5.Text = String.Format("检测耗时:{0}ms", watchTime.ElapsedMilliseconds); } else if (firstSecondFlg == 2) { setControlText(this.label2, String.Format("检测耗时:{0}ms", watchTime.ElapsedMilliseconds)); //this.label2.Text = String.Format("检测耗时:{0}ms", watchTime.ElapsedMilliseconds); } object obj = Marshal.PtrToStructure(faceResPtr, typeof(AFD_FSDK_FACERES)); faceRes = (AFD_FSDK_FACERES)obj; Console.WriteLine(" Face Count:{0}", faceRes.nFace); for (int i = 0; i < faceRes.nFace; i++) { MRECT rect = (MRECT)Marshal.PtrToStructure(faceRes.rcFace + Marshal.SizeOf(typeof(MRECT)) * i, typeof(MRECT)); int orient = (int)Marshal.PtrToStructure(faceRes.lfaceOrient + Marshal.SizeOf(typeof(int)) * i, typeof(int)); if (i == 0) { Image image = CutFace(bitmap, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); if (firstSecondFlg == 1) { this.pictureBox3.Image = image; } else if (firstSecondFlg == 2) { this.pictureBox4.Image = image; } } Console.WriteLine(" left:{0} top:{1} right:{2} bottom:{3} orient:{4}", rect.left, rect.top, rect.right, rect.bottom, orient); } Console.WriteLine(" EndTime:{0}", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ffff")); Console.WriteLine("############### Face Detect End #########################"); if (faceRes.nFace > 0) { Console.WriteLine(); Console.WriteLine("############### Face Recognition Start #########################"); AFR_FSDK_FACEINPUT faceResult = new AFR_FSDK_FACEINPUT(); int orient = (int)Marshal.PtrToStructure(faceRes.lfaceOrient, typeof(int)); faceResult.lfaceOrient = orient; faceResult.rcFace = new MRECT(); MRECT rect = (MRECT)Marshal.PtrToStructure(faceRes.rcFace, typeof(MRECT)); faceResult.rcFace = rect; IntPtr faceResultPtr = Marshal.AllocHGlobal(Marshal.SizeOf(faceResult)); Marshal.StructureToPtr(faceResult, faceResultPtr, false); AFR_FSDK_FACEMODEL localFaceModels = new AFR_FSDK_FACEMODEL(); IntPtr localFaceModelsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(localFaceModels)); //Marshal.StructureToPtr(localFaceModels, localFaceModelsPtr, false); watchTime.Start(); int extractResult = AmFaceVerify.AFR_FSDK_ExtractFRFeature(regcognizeEngine, offInputPtr, faceResultPtr, localFaceModelsPtr); Marshal.FreeHGlobal(faceResultPtr); Marshal.FreeHGlobal(offInputPtr); watchTime.Stop(); if (firstSecondFlg == 1) { setControlText(this.label3, String.Format("抽取特征耗时:{0}ms", watchTime.ElapsedMilliseconds)); //this.label3.Text = String.Format("抽取特征耗时:{0}ms", watchTime.ElapsedMilliseconds); } else if (firstSecondFlg == 2) { setControlText(this.label4, String.Format("抽取特征耗时:{0}ms", watchTime.ElapsedMilliseconds)); //this.label4.Text = String.Format("抽取特征耗时:{0}ms", watchTime.ElapsedMilliseconds); } object objFeature = Marshal.PtrToStructure(localFaceModelsPtr, typeof(AFR_FSDK_FACEMODEL)); Marshal.FreeHGlobal(localFaceModelsPtr); localFaceModels = (AFR_FSDK_FACEMODEL)objFeature; feature = new byte[localFaceModels.lFeatureSize]; Marshal.Copy(localFaceModels.pbFeature, feature, 0, localFaceModels.lFeatureSize); //localFaceModels = new AFR_FSDK_FACEMODEL(); Console.WriteLine("############### Face Recognition End #########################"); } bitmap.Dispose(); imageData = null; Marshal.FreeHGlobal(imageDataPtr); offInput = new ASVLOFFSCREEN(); faceRes = new AFD_FSDK_FACERES(); //Marshal.FreeHGlobal(faceResPtr); } catch (Exception e) { LogHelper.WriteErrorLog("detect", e.Message + "\n" + e.StackTrace); } return feature; } //初始化 private void Form1_Load(object sender, EventArgs e) { #region 初始化人脸检测引擎 int detectSize = 40 * 1024 * 1024; IntPtr pMem = Marshal.AllocHGlobal(detectSize); //1-1 //string appId = "4tnYSJ68e8wztSo4Cf7WvbyMZduHwpqtThAEM3obMWbE"; //1-1 //string sdkKey = "Cgbaq34izc8PA2Px26x8qqWTQn2P5vxijaWKdUrdCwYT"; //1-n string appId = "8b4R2gvcoFQXKbC4wGtnYcqsa9Bd3FLiN3VWDFtJqcnB"; //1-n string sdkKey = "A5Km3QjZKGuakWRmC2pSWTuNzbNbaSCnj5fFtjBBcdxm"; //人脸检测引擎初始化 // IntPtr aaa= AFD_FSDKLibrary.AFD_FSDK_InitialFaceEngine(appId, sdkKey, pMem, detectSize, ref detectEngine, 5, 50, 1); int retCode = AmFaceVerify.AFD_FSDK_InitialFaceEngine(appId, sdkKey, pMem, detectSize, ref detectEngine, 5, 50, 1); //获取人脸检测引擎版本 IntPtr versionPtr = AmFaceVerify.AFD_FSDK_GetVersion(detectEngine); AFR_FSDK_Version version = (AFR_FSDK_Version)Marshal.PtrToStructure(versionPtr, typeof(AFR_FSDK_Version)); Console.WriteLine("lCodebase:{0} lMajor:{1} lMinor:{2} lBuild:{3} Version:{4} BuildDate:{5} CopyRight:{6}", version.lCodebase, version.lMajor, version.lMinor, version.lBuild, Marshal.PtrToStringAnsi(version.Version), Marshal.PtrToStringAnsi(version.BuildDate), Marshal.PtrToStringAnsi(version.CopyRight)); //Marshal.FreeHGlobal(versionPtr); #endregion #region 初始化人脸识别引擎 int recognizeSize = 40 * 1024 * 1024; IntPtr pMemDetect = Marshal.AllocHGlobal(recognizeSize); //1-1 //string appIdDetect = "4tnYSJ68e8wztSo4Cf7WvbyMZduHwpqtThAEM3obMWbE"; //1-1 //string sdkKeyDetect = "Cgbaq34izc8PA2Px26x8qqWaaBHbPD7wWMcTU6xe8VRo"; //1-n string appIdDetect = "8b4R2gvcoFQXKbC4wGtnYcqsa9Bd3FLiN3VWDFtJqcnB"; //1-n string sdkKeyDetect = "A5Km3QjZKGuakWRmC2pSWTuW9zdndn5EkVDo4LceRxLU"; //人脸识别引擎初始化 retCode = AmFaceVerify.AFR_FSDK_InitialEngine(appIdDetect, sdkKeyDetect, pMemDetect, recognizeSize, ref regcognizeEngine); //获取人脸识别引擎版本 IntPtr versionPtrDetect = AmFaceVerify.AFR_FSDK_GetVersion(regcognizeEngine); AFR_FSDK_Version versionDetect = (AFR_FSDK_Version)Marshal.PtrToStructure(versionPtrDetect, typeof(AFR_FSDK_Version)); Console.WriteLine("lCodebase:{0} lMajor:{1} lMinor:{2} lBuild:{3} lFeatureLevel:{4} Version:{5} BuildDate:{6} CopyRight:{7}", versionDetect.lCodebase, versionDetect.lMajor, versionDetect.lMinor, versionDetect.lBuild, versionDetect.lFeatureLevel, Marshal.PtrToStringAnsi(versionDetect.Version), Marshal.PtrToStringAnsi(versionDetect.BuildDate), Marshal.PtrToStringAnsi(versionDetect.CopyRight)); #endregion } //拖拽事件 private void Form1_DragDrop(object sender, DragEventArgs e) { // Extract the data from the DataObject-Container into a string list string[] fileList = (string[])e.Data.GetData(DataFormats.FileDrop, false); if (fileList.Length >= 2) { this.threadMultiExec = new Thread(new ParameterizedThreadStart(multiCompare)); this.threadMultiExec.Start(new object[] { fileList }); this.threadMultiExec.IsBackground = true; } } private void Form1_DragEnter(object sender, DragEventArgs e) { // Check if the Dataformat of the data can be accepted // (we only accept file drops from Explorer, etc.) if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.Copy; // Okay } else { e.Effect = DragDropEffects.None; // Unknown data, ignore it } } //多线程设置PictureBox的图像 private void setPictureBoxControlImage(PictureBox control, Bitmap value) { control.Invoke(new Action((ct, v) => { ct.Image = v; }), new object[] { control, value }); } //多线程设置控件的文本 private void setControlText(Control control, string value) { control.Invoke(new Action((ct, v) => { ct.Text = v; }), new object[] { control, value }); } //比对多个图片 private void multiCompare(object args) { object[] objs = args as object[]; string[] fileList = (string[])objs[0]; for (int i = 0; i < fileList.Length; i++) { Image image = Image.FromFile(fileList[i]); //this.pictureBox1.Image = null; //this.pictureBox1.Image = new Bitmap(image); setPictureBoxControlImage(this.pictureBox1, new Bitmap(image)); firstFeature = detectAndExtractFeature(image, 1); image.Dispose(); if (firstFeature == null) { continue; } if (i + 1 >= fileList.Length) { continue; } Image image2 = Image.FromFile(fileList[++i]); //this.pictureBox2.Image = null; // this.pictureBox2.Image = new Bitmap(image2); setPictureBoxControlImage(this.pictureBox2, new Bitmap(image2)); secondFeature = detectAndExtractFeature(image2, 2); image2.Dispose(); if (secondFeature == null) { continue; } button3_Click(null, null); setControlText(this.label6, "正在处理:" + (i + 1).ToString()); //label6.Text = "正在处理:" + (i + 1).ToString(); //this.Update(); Thread.Sleep(10); } } } }
USB视频 动态画框 源码下载地址 https://download.csdn.net/download/zhang1244/10368237 运行效果地址 https://download.csdn.net/download/zhang1244/10368222 普通人脸照片进行关键点提取以及相关对比相似度
https://download.csdn.net/download/zhang1244/10368197
运行效果地址
https://download.csdn.net/download/zhang1244/10368181
相关技术交流,后期可能开发相关与身份证照片进行实名制对比。请继续关注
USB视频 动态画框 源码下载地址 https://download.csdn.net/download/zhang1244/10368237 运行效果地址 https://download.csdn.net/download/zhang1244/10368222 普通人脸照片进行关键点提取以及相关对比相似度
https://download.csdn.net/download/zhang1244/10368197
运行效果地址
https://download.csdn.net/download/zhang1244/10368181
人工智能
2019-03-25 15:47:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
两个整形无序数组,数据大小[0-9],数组内元素不重复,尽量快地找出两个数组中相同元素的个数。
相亲、旅游问题抽象
例子:
[2,6,9,3,1]与[3,2,4,6],相同元素个数为3
[3,1,5,2,4,9,8]与[6,2,7],相同元素个数为1
思路:
因为数据大小为0-9,数组元素不重复,所以可以先把两个数组转成二进制数字,然后再对比两个数据相同1的个数
伪代码:
let arrayA:[Int] = [2,6,9,3,1]
let arrayB:[Int] = [3,2,4,6]
// 计算A数组的二进制
var resultBinA: Int64 = 0
for item: Int in arrayA {
resultBinA = resultBinA | (1 << item)
}
// 计算A数组的二进制
var resultBinB: Int64 = 0
for item: Int in arrayB {
resultBinB = resultBinB | (1 << item)
}
// 计算相同1个数
let compareResult: Int64 = resultBinB & resultBinA
let compareString: String = String(compareResult, radix:2)
let onlyOneString = compareString.replacingOccurrences(of: "0", with: "")
Alert(onlyOneString.count)
人工智能
2019-03-25 15:22:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
本博客包含三个常用方法,用于盛开Android版人脸识别Demo中竖屏使用时送入yuv数据,但一直无法识别的情况。 1.首先可以尝试顺时针旋转90°或270°,然后送入识别SDK。 2.旋转方向后依然无法识别时,可以尝试saveImg( ),保存本地检查图片是否符合要求。
/** * 视频顺时针旋转90 * 该方法仅仅在竖屏时候使用 * */ public static byte[] rotateYUV420Degree90(byte[] data, int imageWidth, int imageHeight) { byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2]; int i = 0; for (int x = 0; x < imageWidth; x++) { for (int y = imageHeight - 1; y >= 0; y--) { yuv[i] = data[y * imageWidth + x]; i++; } } i = imageWidth * imageHeight * 3 / 2 - 1; for (int x = imageWidth - 1; x > 0; x = x - 2) { for (int y = 0; y < imageHeight / 2; y++) { yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x]; i--; yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + (x - 1)]; i--; } } return yuv; } public static byte[] YUV420spRotate270(byte[] src, int width, int height) { int count = 0; int uvHeight = height >> 1; int imgSize = width * height; byte[] des = new byte[imgSize * 3 >> 1]; //copy y for (int j = width - 1; j >= 0; j--) { for (int i = 0; i < height; i++) { des[count++] = src[width * i + j]; } } //u,v for (int j = width - 1; j > 0; j -= 2) { for (int i = 0; i < uvHeight; i++) { des[count++] = src[imgSize + width * i + j - 1]; des[count++] = src[imgSize + width * i + j]; } } return des; } private int i = 1; private String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/0Face/"; private Calendar now = new GregorianCalendar(); private SimpleDateFormat simpleDate = new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()); private String fileName = simpleDate.format(now.getTime()); /** * @param data yuv图像数据 * @param width * @param height */ public void saveImg(byte[] data, int width, int height) { File dir = new File(path); if (!dir.exists()) dir.mkdirs(); File f = new File(path + (fileName + "-" + i++) + ".jpg"); FileOutputStream fOut = null; try { //yuv转成bitmap YuvImage image = new YuvImage(data, ImageFormat.NV21, width, height, null); ByteArrayOutputStream stream = new ByteArrayOutputStream(); image.compressToJpeg(new Rect(0, 0, width, height), 80, stream); Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size()); //bitmap保存至本地 fOut = new FileOutputStream(f); bmp.compress(Bitmap.CompressFormat.JPEG, 100, fOut); fOut.flush(); fOut.close(); bmp.recycle(); stream.close(); } catch (Exception ex) { Log.e("Sys", "Error:" + ex.getMessage()); } }
人工智能
2019-03-25 14:32:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
N-最短路径 是中科院分词工具NLPIR进行分词用到的一个重要算法,张华平、刘群老师在论文《基于N-最短路径方法的中文词语粗分模型》中做了比较详细的介绍。该算法算法基本思想很简单,就是给定一待处理字串,根据词典,找出词典中所有可能的词,构造出字串的一个有向无环图,算出从开始到结束所有路径中最短的前N条路径。因为允许相等长度的路径并列,故最终的结果集合会大于或等于N。
根据算法思想,当我们拿到一个字串后,首先构造图,接着针对图计算最短路径。下面以一个例子“他说的确实在理”进行说明,开始为了能够简单说明,首先假设图上的边权值均为1。
先给出对这句话的3-最短路(即路径最短的前3名, 因为有并列成分, 所以可能候选路径大于3)径求解过程图:
从节点4开始, 因为4是第一个出现多个前驱节点的
首先看图中上方,它是根据一个已有词典构造出的有向无环图。它将字串分为单个的字,每个字用图中相邻的两个结点表示,故对于长度为n的字串,需要n+1个结点。两节点间若有边,则表示两节点间所包含的所有结点构成的词,如图中结点2、3、4构成词“的确”。
图构造出来后,接下来就要计算最短路径,N-最短路径是基于Dijkstra算法的一种简单扩展,它在每个结点处记录了N个最短路径值与该结点的前驱,具体过程如上图中下方列表。Table(4)表示位于结点4时的最短路径情况,表示从结点0到4有两条路径,长度为3的路径前驱为2;长度为4的路径前驱为3。前驱括号里面第二个数表示对相同前驱结点的区分,如(4,1)、(4,2)。由列表可知,该字串的3-最短路径结果集合为{5,5,6,6,7}。
当然,在实际情况中,权值不可能都设为1的,否则随着字串长度n和最短路径N的增大,长度相同的路径数将会急剧增加。为了解决这样的问题,我们需要通过某种策略为有向图的边赋权重,很自然的想法就是边的权重就是该词出现的可能性。
NShortPath的基本思想是Dijkstra算法的变种,拿1-最短路来说吧,先Dijkstra求一次最短路,然后沿着最短路的路径走下去,只不过在走到某个节点的时候,检查到该节点在路径上的下一个节点是否还有别的路到它(从PreNode查),如果有,就走这些别的路中的没走过第一条(它们都是最短路上的途径节点)。然后推广到N-最短路,N-最短路中PreNode有N个,分别对应n-最短路时候的PreNode,就这么简单。
图解
再谈PreNode的准备
需要为每个顶点维护一个最小堆,最小堆里储存的是边的花费,每条边的终点是这个顶点。还需要维护到每个顶点的前N个最小路径的花费:
回忆一下Dijkstra求最短路的时候,我们只需记录一个最短路的累计花费就行了
这与此处的N-最短路径显著不同。
在遍历图的时候,与Dijkstra最短路径不同,N-最短路径从第二个节点开始,需要将当前节点可能到达的边根据累积第i短长度+该边的长度之和排序记录到PreNode队列数组中,排序由CQueue完成的。
然后从CQueue出队,这样路径长度就是升序了,按顺序更新 weightArray[当前节点][第几短路]就行了。
另外CQueue是一个不同于普通队列的队列,它维护了一个当前指针(下图的蓝色部分),这个蓝色指针在求解第i短路径的时候会用到。
假定看到这里,算法已经计算出了正确的PreNode队列,下面讨论如何从PreNode中找出N最短路径的确切途经节点集合。
1-最短路径的求解
整个计算过程维护了一个路径栈,对于上图来说,
1)首先将最后一个元素压入栈(本例中是6号结点),什么时候这个元素弹出栈,什么时候整个任务结束。
2)对于每个结点的PreNode队列,维护了一个当前指针,初始状态都指向PreNode队列中第一个元素。这个指针是由CQueue维护的,严格来讲不属于算法关心的问题。
3)从右向左依次取出PreNode队列中的当前元素(当前元素出队)并压入栈,并将队列指针重新指向队列中第一个元素。如上图:6号元素PreNode是3,3号元素PreNode是1,1号元素PreNode是0。
4)当第一个元素压入栈后,输出栈内容即为一条队列。本例中0, 1, 3, 6便是一条最短路径。
5)将栈中的内容依次弹出,每弹出一个元素,就将当时压栈时该元素对应的PreNode队列指针下移一格。如果到了末尾无法下移,则继续执行第5步(也就是继续出栈),如果仍然可以移动,则执行第3步。
对于本例,先将“0”弹出栈,在路径上0的下一个是1,得出该元素对应的是1号“A”结点的PreNode队列,该队列的当前指针已经无法下移,因此继续弹出栈中的“1” ;同理该元素对应3号“C”结点,因此将3号“C”结点对应的PreNode队列指针下移。由于可以移动,因此将队列中的2压入队列,2号“B”结点的PreNode是1,因此再压入1,依次类推,直到0被压入,此时又得到了一条最短路径,那就是0,1,2,3,6。如下图:
再往下,0、1、2都被弹出栈,3被弹出栈后,由于它对应的6号元素PreNode队列记录指针仍然可以下移,因此将5压入堆栈并依次将其PreNode入栈,直到0被入栈。此时输出第3条最短路径:0, 1, 2, 4, 5, 6。如下图:
输出完成后,紧接着又是出栈,此时已经没有任何栈元素对应的PreNode队列指针可以下移,于是堆栈中的最后一个元素6也被弹出栈,此时输出工作完全结束。我们得到了3条最短路径,分别是:
0, 1, 3, 6,
0, 1, 2, 3, 6,
0, 1, 2, 4, 5, 6,
推广到N-最短路
N-最短路中PreNode有N个,分别对应n-最短路时候的PreNode,也就是当前路径是第n短的时候,当前节点对应的PreNode队列。
在该图中,观察黄颜色的路径长度表格,到达1号、2号、3号结点的路径虽然有多条,但长度只有一种长度,但到达4号“D”结点的路径长度有两种,即长度可能是3也可能是4,此时在“最短路”处(index=0)记录长度为3时的PreNode,在“次短路”处(index=1)处记录长度为4时的PreNode,依此类推。
值得注意的是,此时用来记录PreNode的坐标已经由前文求“1-最短路径”时的一个数(ParentNode值)变为2个数(ParentNode值以及index值)。
如上图所示,到达6号“末”结点的次短路径有两个ParentNode,一个是index=0中的4号结点,一个是index=1的5号结点,它们都使得总路径长度为6。
当N=2时,我们求得了2-最短路径,路径长度有两种,分别长度为5和6,而路径总共有6条,如下:
最短路径:
0, 1, 3, 6,
0, 1, 2, 3, 6,
0, 1, 2, 4, 5, 6,
========================
次 短路径
0, 1, 2, 4, 6,
0, 1, 3, 4, 5, 6,
0, 1, 2, 3, 4, 5, 6,
---------------------
人工智能
2019-03-25 11:49:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
https://hccl.ioa.ac.cn/output/papers/
人工智能
2019-03-24 10:31:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
https://zerospeech.com/2015/index.html
人工智能
2019-03-24 10:22:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
目前我们的应用内使用了 ArcFace 的人脸检测功能,其他的我们并不了解,所以这里就和大家分享一下我们的集成过程和一些使用心得 集成 ArcFace FD 的集成过程非常简单 在 ArcFace FD 的文档上有说明支持的系统为 5.0 及以上系统,但其实在 4.4 系统上也是可以跑的, if (engine == null) { // && Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { try { engine = new AFD_FSDKEngine(); AFD_FSDKError err = engine.AFD_FSDK_InitialFaceEngine( "XXXX", "XXXX", AFD_FSDKEngine.AFD_OPF_0_HIGHER_EXT, 12, 3); if (err.getCode() != 0) { engine.AFD_FSDK_UninitialFaceEngine(); engine = null; } } catch (Exception e) { e.printStackTrace(); engine = null; } }
我觉得 ArcFace 的优势除了多角度检测之外,另外一个是他的每次检测并不是独立,即这一次的检测结果会指导下一次的检测 (我猜测的->_->) 所以 ArcFace 在检测到人脸之后,识别的时间会大幅减少,而 Seeta FD 的检测每次都是独立的,所以在无人脸的情况下,Seeta 的检测速度要快于 ArcFace, 但是检测到人脸之后,因为应用整体的计算量增加,导致 Seeta 的检测速度降低的非常明显,大大慢于 ArcFace, (所以二者是不是可以结合一下...) AFD_FSDKError err = engine.AFD_FSDK_StillImageFaceDetection( data, width, height, AFD_FSDKEngine.CP_PAF_NV21, result);
优化 不得不说 ArcFace FD 的错误率是有待优化的,虽然 ArcFace 没有提供任何可以调节的参数,但是还是可以稍微优化一下!
因为从摄像头出来的 yuv 数据是横向的,而 ArcFace 只有 AFD_OPF_0_HIGHER_EXT 这个扩展选项,优先检测 0 度方向, 但是这个方向一般是没有人脸的,所以如果直接进行检测,我们觉得这个可能会增加检测的错误率(猜的->_->),所以处理方法是将 yuv 旋转到手机竖屏方向(当然这个操作不是直接由 CPU 来处理,而是从 Camera 的外部纹理上开始做操作)再拿去检测,这样会减少一点错误率(从用户反馈得出),虽然错误率依然很高(特别对于带栅格的物体)希望虹软能继续优化!
另外一个是目前 ArcFace 还没有支持 Android 8.x 系统,所以这种情况下,我们会启用备选的其他方案来进行人脸检测!
最后希望虹软能把 ArcFace 越做越好 _ 因为只有产品足够好才会不断的有人为你做免费宣传 查看更多分享戳☞ArcFace Android 人脸检测集成分享
人工智能
2019-03-22 16:28:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
最近在研究虹软家的arcface 人脸识别 demo,现在就给大家分享一下官方的demo ** 工程如何使用?
** 1.下载代码: git clone https://github.com/asdfqwrasdf/ArcFaceDemo.git 或者直接下载压缩包
2.前往官网申请appid和sdkkey。 修改 ArcFaceDemo-master\src\main\java\com\arcsoft\sdk_demo\FaceDB.java 下面的对应的值: public static String appid = "xxxx"; public static String fd_key = "xxxx"; public static String ft_key = "xxxx"; public static String fr_key = "xxxx";
3.下载sdk包之后,解压各个包里libs中的文件到 ArcFaceDemo-master\libs 下,同名so直接覆盖。 4.Android Studio3.0 中直接打开或者导入Project,编译运行即可。 ** demo如何使用? ** 1.点击第一个按钮 打开图片或者拍一张带人脸的照片,确认后自动执行人脸,弹出注册框,注册第一个人脸。 注册界面底部会展示已注册的信息列表,点击列表项,则可以执行删除操作。 2.点击第二个按钮 选择打开前置或者后置的镜头进行检测。 ** demo中人脸数据的保存方式? **  以注册时人名为关键索引,保存在face.txt中。  创建的 name.data 则为实际的数据存储文件,保存了所有特征信息。  同一个名字可以注册多个不同状态角度的人脸,在name.data 中连续保存,占用的数据文件长度为:  N * {4字节(特征数据长度) + 22020字节(特征数据信息)}
最低支持的API-LEVEL?  14-27 ** Issue Report ** 1.before report please check the closed issues. 2.issue format a.错误信息:log,input image,core stack, etc… b.设备信息:cpu, memory, device name, etc… c.系统版本:OS version, API leve,etc… d.具体操作流程:which step,how to recurrence,etc… ** FAQ ** 1.Gradle 错误提示 Error:Failed to find target with hash string ‘android-24’… 一般Android Studio 窗口会有个链接(Install missing platform(s) and sync project) 点击下载更新 android-24 即可解决(其他版本没测试过,建议不要随意更改)。
2.加载图片注册时Crash. NV21格式限制高度和宽度不能同时为奇数,demo已经对这个做了保护。 如有发生,请提供图像尺寸和发生时的全部log。
3.年龄和性别检测结果准确度不够. Video的接口性能优先,Image的接口准确度优先。
4.com.guo.android_extend:android-extend 找不到依赖. 此第三方库android_extend 用来简化camera调用,提供简单的工具方便demo开发。 一般android studio会自动从jcenter 下载对应的aar包,如果没有自动下载,请自行检查是否网络问题,或者删掉build等编译目录,重新运行gradle.
5.还有其他问题. 直接提交issue 我们会尽快解决
6.demo github 地址 https://github.com/asdfqwrasdf/ArcFaceDem
人工智能
2019-03-22 15:52:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
众所周知传统做字的人力成本非常之高,如果全靠人类设计师来完成,一套标准字库从设计到完成需要一年多的时间。而现在,机器解放人类。AI字体设计师将人力成本降到一半,人机比降到50%左右甚至更低。2018年4月份,阿里巴巴联手汉仪字库发布了全球第一款人工智能中文——阿里汉仪智能黑体。
经过一年的进化升级,2019年3月中旬,阿里巴巴与汉仪再发大招,一次性推出五款由汉仪字库协同阿里人机自然交互实验室,通过强大的计算能力自学生成的不同风格人工智能字体。
除了首款阿里汉仪智能黑体针对阿里平台用户免费之外,这五款人工智能字体也将发布后在设计服务市场开放下载,以非常低的售价提供给阿里用户在阿里平台进行使用。 适合多种轻松童趣的行业应用场景的汉仪天真体。 特别适合活动营销和中国风等场合的手写字体汉仪迪升英雄体。 传承文化之情感,共铸新时代的汉仪金陵刻经体。 极具女性视觉语言的圆体汉仪晓波花月圆。 适合古朴历史的行业应用的汉仪碑刻黑。
区别于2018年4月份推出的具有强烈的对话特性和很强的通用性,适用于绝对多数品类商品的阿里汉仪智能黑体,本次阿里与汉仪新推出的五款人工智能字体的适用范围更加垂直,能够更加契合的垂直领域电商的产品气质,从用户的角度出发,深耕细化领域,相信以后会有更多适合细分领域的人工智能字体相继推出,就像阿里巴巴所一直输出的核心价值一样——让天下没有难做的生意。
原文链接
人工智能
2019-03-20 11:04:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
1、 hanlp简介
HanLP是一系列模型与算法组成的NLP工具包,由大快搜索主导并完全开源,目标是普及自然语言处理在生产环境中的应用。HanLP具备功能完善、性能高效、架构清晰、语料时新、可自定义的特点。
开源网址:HanLP: Han Language Processing
但由于hanlp是用java来实现的,要在python中使用hanlp,只能通过调用pyhanlp这个包来。
但是pyhanlp里面有一些功能仍然不支持python直接调用,比如汉字转拼音,这时候就需要从python中启动jvm并指定Hanlp的jar路径来使用其他功能了。
2 、下载并配置文件
(1)从开源网址中下载jar、data、hanlp.properties并修改配置文件:
1、下载:data.zip
下载后解压到任意目录,接下来通过配置文件hanlp.properties告诉HanLP数据包的位置。
data

├─dictionary
└─model
用户可以自行增删替换,如果不需要句法分析等功能的话,随时可以删除model文件夹。
3 、下载jar和配置文件:hanlp-release.zip
(1)配置文件hanlp.properties的作用是告诉HanLP数据包的位置,只需修改第一行为data的父目录即可:
root=D:/JavaProjects/HanLP/
比如data目录是/Users/hankcs/Documents/data,那么root=/Users/hankcs/Documents/ 。
(2)从python中启动jvm以及添加jar包路径

其中-Djava.class.path是用来添加jar包到classpath中,然后用startJVM来启动jvm。
startJVM第一个参数是系统内的jvm位置,第二个为*arg参数,此处放置classpath。
以上得到的是java的ArrayList类型,需要将他装换为string类型:
结果如下:
4 、最后记得关闭JVM

--------------------
作者:Juanly Jack
人工智能
2019-03-20 10:17:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
伴随着技术的发展和应用场景的拓宽,人工智能已经不再被视为一个全新的概念。在某种程度上,人工智能已经被视为与水或空气一般的存在。但广阔的发展前景与国内捉襟见肘的人才储备严重脱节——根据领英此前发布的报告显示,中国的AI人才储备仅为美国的1/15左右。
为了应对AI领域中产学研脱节现象,百度推出了专门面向高校教育需求的一站式AI教学服务平台——AI Studio教育版。上线一周,后台已收到了超过50名高校教师的咨询和权限开通申请,百度组建了专门的服务支持小组,解答教师的疑问。下面我们为大家提供了AI Studio教育版的详细操作评测。



AI Studio教育版首页
让AI课堂一站式搭建
与传统计算机软件教育有所不同,AI教育课程不仅更加注重丰富案例和项目实践,同时在实操过程中难以仅仅依赖单机完成,对实验设备、计算资源的需求,也成为老师开课中的一大难题。如何让AI课堂最小成本、最快速高效的建立起来?这成为高等院校开展AI教学时首先需要思考的问题。
一方面,云端教学课堂的搭建将让教学资源的共享成为现实;另一方面,课堂本身师生之间的互动将可追溯、可归因,老师既能实时了解学生掌握相关知识的动态并以此调整教学计划,也能让学生拥有随时随地接触学习素材的条件。
在AI Studio教育版中,教师能够通过点选操作快速组建属于自己的教学班级;与此同时,不同班级的学生也能在自身权限内共享老师提供的所有教学材料。无论对于教师或是学生而言,这样的在线教学模式都能够达到“事半功倍”的效果。



教师使用AI Studio教育版开展教学活动的基本流程
与传统的在线课堂不同,AI Studio教育版的亮点在于将庞大的教学资源库开放给了高校的师生们。当教师组建教学班级之后,百度官方制作的教案、数据集等宝贵资源也将被老师们各取所需地采用,老师们可以根据已有资源制定教学计划、布置课堂作业、进行在线训练,乃至参与或组织相关的AI比赛等等。
借助云端资源的大量共享,分布在不同地域、不同学校、具有不同教育背景与从业经历的师生们都能共同受惠于这套在线教学系统。更为重要的是,象牙塔中理论知识的储备在多元形式的辅助下有了落地和实践的可能,这套课堂建构的逻辑刚好贴合了当下人才培养层面的刚性需求。
AI课堂素材不再捉襟见肘
在教育版的前期产品调研中,教师们反复提及的一个痛点是:理论我们懂,但没有可供学生实践、教学演示的项目素材,“理论结合实践”缺了一条腿。教师们要么舍弃实践环节纯讲理论,要么就只能手把手地、耗费大量的时间和精力成本构建自己的素材,性价比极低。
针对这一痛点,AI Studio教育版的推出让教学素材质量更高、获取更加便捷,并且其价值还在不同的教学课堂中持续被挖掘出来。这种中央厨房式的“统一输出、按需分配”,不仅让教师的自主权得到保障,同时也保证了课堂教学具备高质量完成的可能性。


AI Stuido教育版上线了一套教学Notebook案例,并将持续更新
目前提供的Notebook案例已经涵盖了各个层面,从豆瓣高分电影爬取到鸢尾花分类,从波士顿房价预测再到人脸识别等等。不同门类、不同深度的素材必然会成为人工智能领域的高校教师开展教学工作的“富矿”。
根据不同的课程规划,教师们可以从百度AI学习项目/我的项目目录中选择Notebook添加进相应课节,添加的过程也十分简单——老师们只需要选择合适的案例点击确定按钮,便能完成相应素材从资源池向课堂的导入。


教师只要在AI Studio上添加节课的内容,相应授课素材就会自动导入
教学过程的高度“自定义”
虽然在AI Studio教育版的幕后有百度这个明显的影子,但是百度在进行资源对接和课程开发时,并未要求各个高校遵循统一的教学流程和标准。相反,这套教学产品给予了教师和学生极大的“自定义”权利。
譬如对教师而言,当组建完自己的班级之后便面临着制定具体教学计划和方案的任务。在AI Studio教育版中,教师可以设置“即将开始”、“进行中”、“已结束”等不同的班级状态,系统将根据不同的状态赋能各不相同的功能。
每位老师可以设置20个不同班级,分别设置教学内容,并根据自己的教学规划设定每套课及课节的名称,以适应不同教学方法与进度。


教师创建的班级在个人后台一目了然,方便教师进行班级管理
教师还可以在班级介绍栏中阐明班级的教学目标、特色以及其他注意事项等,并能将自己的教学成果、研究方向、科研状况等个人信息全面地向学生展示。这种将基础信息前置化展示的操作,能让师生之间的相互了解在课程开始之前便开始。



教师可以在创建班级页面,对班级的各类信息进行编辑
师生高效互动与学习效果监测
“教学”是教与学的相辅相成。AI Stduio教育版想要老师学生用得了、用得好,建立一个足够高效的互动机制必不可少。
在每位教师专属的班级管理后台中,老师们能够应需进行学生的管理,例如通过验证码认证学生身份,增删、编辑自己班级的学生信息,并对学生权限进行设置。
当已认证的班级学生开始学习后,老师们便能在项目统计的子模块中观看学生的实时学习情况。例如可以进入到学生Notebook项目预览页面,查看学生在不同课节的实践项目完成情况;当学生完成了相关项目后,便能根据学生的完成情况给予不同的分值;与此同时,教师还能够在后台评判学生项目是否通过,从而判断学生的学习成绩合格与否。
在线的学习效果监测不仅对于学生有着督促学习的作用,也将让老师不断审视自身的教学计划和相关实践案例引入是否合适,从而实现教学过程的动态与实时调整。



每个学生的学习情况,都可以在后台进行统计监督
从以上种种操作设置,不难发现AI Studio教育版是基于真实的教学场景搭建出来的,研发初期便充分考虑了教师的实际需求,以及这些需求如何完成“互联网+”到“AI+”的转型——对于教师而言,极简操作不需要额外的学习过程,而学生也能极快地“上手”,并能从这套系统中发现更多在原有教学场景下无法挖掘出的信息。据了解,AI Studio教育版还将继续开放助教权限、自动评分等功能,进一步完善和满足高校教学场景的需求。
总的来说,百度AI Studio教育版的推出解决了高校人工智能人才培养方面的燃眉之急,它在抽象理论和具体实践间搭起了一座桥梁,让原本相互隔离的象牙塔和社会实践有了对话的可能。事实上,人工智能的真正价值不可能只发挥在实验室中,它必然需要走出去完成与社会场景的对接,并借此展现自身的社会价值,百度显然为高校里的AI资源搭建了一个更加宏大的舞台。
无论是整体的逻辑框架,还是微观的功能设置,AI Studio教育版都在一定程度上符合了李彦宏此前的宏愿——Everyone can AI。至少在高校的语境中,它正在让理想逐渐走入现实。
人工智能
2019-03-19 19:29:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
伴随着技术的发展和应用场景的拓宽,人工智能已经不再被视为一个全新的概念。在某种程度上,人工智能已经被视为与水或空气一般的存在。但广阔的发展前景与国内捉襟见肘的人才储备严重脱节——根据领英此前发布的报告显示,中国的AI人才储备仅为美国的1/15左右。
为了应对AI领域中产学研脱节现象,百度推出了专门面向高校教育需求的一站式AI教学服务平台——AI Studio教育版。上线一周,后台已收到了超过50名高校教师的咨询和权限开通申请,百度组建了专门的服务支持小组,解答教师的疑问。下面我们为大家提供了AI Studio教育版的详细操作评测。 下载安装命令 ## CPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle ## GPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu

AI Studio教育版首页
让AI课堂一站式搭建
与传统计算机软件教育有所不同,AI教育课程不仅更加注重丰富案例和项目实践,同时在实操过程中难以仅仅依赖单机完成,对实验设备、计算资源的需求,也成为老师开课中的一大难题。如何让AI课堂最小成本、最快速高效的建立起来?这成为高等院校开展AI教学时首先需要思考的问题。
一方面,云端教学课堂的搭建将让教学资源的共享成为现实;另一方面,课堂本身师生之间的互动将可追溯、可归因,老师既能实时了解学生掌握相关知识的动态并以此调整教学计划,也能让学生拥有随时随地接触学习素材的条件。
在AI Studio教育版中,教师能够通过点选操作快速组建属于自己的教学班级;与此同时,不同班级的学生也能在自身权限内共享老师提供的所有教学材料。无论对于教师或是学生而言,这样的在线教学模式都能够达到“事半功倍”的效果。


教师使用AI Studio教育版开展教学活动的基本流程
与传统的在线课堂不同,AI Studio教育版的亮点在于将庞大的教学资源库开放给了高校的师生们。当教师组建教学班级之后,百度官方制作的教案、数据集等宝贵资源也将被老师们各取所需地采用,老师们可以根据已有资源制定教学计划、布置课堂作业、进行在线训练,乃至参与或组织相关的AI比赛等等。
借助云端资源的大量共享,分布在不同地域、不同学校、具有不同教育背景与从业经历的师生们都能共同受惠于这套在线教学系统。更为重要的是,象牙塔中理论知识的储备在多元形式的辅助下有了落地和实践的可能,这套课堂建构的逻辑刚好贴合了当下人才培养层面的刚性需求。
AI课堂素材不再捉襟见肘
在教育版的前期产品调研中,教师们反复提及的一个痛点是:理论我们懂,但没有可供学生实践、教学演示的项目素材,“理论结合实践”缺了一条腿。教师们要么舍弃实践环节纯讲理论,要么就只能手把手地、耗费大量的时间和精力成本构建自己的素材,性价比极低。
针对这一痛点,AI Studio教育版的推出让教学素材质量更高、获取更加便捷,并且其价值还在不同的教学课堂中持续被挖掘出来。这种中央厨房式的“统一输出、按需分配”,不仅让教师的自主权得到保障,同时也保证了课堂教学具备高质量完成的可能性。

AI Stuido教育版上线了一套教学Notebook案例,并将持续更新
目前提供的Notebook案例已经涵盖了各个层面,从豆瓣高分电影爬取到鸢尾花分类,从波士顿房价预测再到人脸识别等等。不同门类、不同深度的素材必然会成为人工智能领域的高校教师开展教学工作的“富矿”。
根据不同的课程规划,教师们可以从百度AI学习项目/我的项目目录中选择Notebook添加进相应课节,添加的过程也十分简单——老师们只需要选择合适的案例点击确定按钮,便能完成相应素材从资源池向课堂的导入。

教师只要在AI Studio上添加节课的内容,相应授课素材就会自动导入
教学过程的高度“自定义”
虽然在AI Studio教育版的幕后有百度这个明显的影子,但是百度在进行资源对接和课程开发时,并未要求各个高校遵循统一的教学流程和标准。相反,这套教学产品给予了教师和学生极大的“自定义”权利。
譬如对教师而言,当组建完自己的班级之后便面临着制定具体教学计划和方案的任务。在AI Studio教育版中,教师可以设置“即将开始”、“进行中”、“已结束”等不同的班级状态,系统将根据不同的状态赋能各不相同的功能。
每位老师可以设置20个不同班级,分别设置教学内容,并根据自己的教学规划设定每套课及课节的名称,以适应不同教学方法与进度。


教师创建的班级在个人后台一目了然,方便教师进行班级管理
教师还可以在班级介绍栏中阐明班级的教学目标、特色以及其他注意事项等,并能将自己的教学成果、研究方向、科研状况等个人信息全面地向学生展示。这种将基础信息前置化展示的操作,能让师生之间的相互了解在课程开始之前便开始。


教师可以在创建班级页面,对班级的各类信息进行编辑
师生高效互动与学习效果监测
“教学”是教与学的相辅相成。AI Stduio教育版想要老师学生用得了、用得好,建立一个足够高效的互动机制必不可少。
在每位教师专属的班级管理后台中,老师们能够应需进行学生的管理,例如通过验证码认证学生身份,增删、编辑自己班级的学生信息,并对学生权限进行设置。
当已认证的班级学生开始学习后,老师们便能在项目统计的子模块中观看学生的实时学习情况。例如可以进入到学生Notebook项目预览页面,查看学生在不同课节的实践项目完成情况;当学生完成了相关项目后,便能根据学生的完成情况给予不同的分值;与此同时,教师还能够在后台评判学生项目是否通过,从而判断学生的学习成绩合格与否。
在线的学习效果监测不仅对于学生有着督促学习的作用,也将让老师不断审视自身的教学计划和相关实践案例引入是否合适,从而实现教学过程的动态与实时调整。


每个学生的学习情况,都可以在后台进行统计监督
从以上种种操作设置,不难发现AI Studio教育版是基于真实的教学场景搭建出来的,研发初期便充分考虑了教师的实际需求,以及这些需求如何完成“互联网+”到“AI+”的转型——对于教师而言,极简操作不需要额外的学习过程,而学生也能极快地“上手”,并能从这套系统中发现更多在原有教学场景下无法挖掘出的信息。据了解,AI Studio教育版还将继续开放助教权限、自动评分等功能,进一步完善和满足高校教学场景的需求。
总的来说,百度AI Studio教育版的推出解决了高校人工智能人才培养方面的燃眉之急,它在抽象理论和具体实践间搭起了一座桥梁,让原本相互隔离的象牙塔和社会实践有了对话的可能。事实上,人工智能的真正价值不可能只发挥在实验室中,它必然需要走出去完成与社会场景的对接,并借此展现自身的社会价值,百度显然为高校里的AI资源搭建了一个更加宏大的舞台。
无论是整体的逻辑框架,还是微观的功能设置,AI Studio教育版都在一定程度上符合了李彦宏此前的宏愿——Everyone can AI。至少在高校的语境中,它正在让理想逐渐走入现实。
>> 访问 PaddlePaddle 官网, 了解更多相关内容 。 下载安装命令 ## CPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle ## GPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu
人工智能
2019-03-19 19:28:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
解决atsl vin码不一致问题:
1、停车20分钟,彻底关闭中控
2、启动车辆
3、卸载Cadillac品牌app
4、在设置-恢复出厂菜单中依次执行:2(删除程序缓存)-1(恢复出厂)-3(清除默认程序)
5、车辆熄火,并开关一次车门
6、启动车辆,并让车辆连接手机热点
7、进入软件中心下载Cadillac 品牌 app
8、下载完了之后,右上角登录。然后在个人中心中即可看到vin码已经正确
9、在中控菜单中找到用户,新建用户资料。如果已关联了原用户的手机号,则可以直接关联
10、重新在软件中心下载Cadillac应用,右上角点击登录即可
人工智能
2019-03-19 18:31:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
在第一期“漫说安全”栏目中,我们用四格漫画的形式介绍了基于深度学习的阿里云WAF到底智能在哪里,能帮客户解决什么问题。
在今天的这期栏目里,我们依然通过漫画这种通俗易懂的方式,与大家分享阿里云WAF的另一大特点—开放。开放的云WAF到底有什么好处,答案就在漫画里^_^

漫画看完,安全君依旧准备了问答环节哦
客户:云盾WAF具有哪些开放特征?
安全小二: 1.开放的OpenAPI接口支持;2.自定义规则组配置;3.基于大数据的全量日志实时存储、分析服务。
客户:OpenAPI接口带来的最主要价值是什么?
安全小二: 支持快速程序化配置和第三方平台调用和集成,助力客户自动化安全运营和统一平台运营,提高工作效率。
客户:规则开放后为日常防护带来什么好处?
安全小二: 云盾WAF是国内首个做到将规则定义权交付给客户的,客户可以在专家策略基础之上,基于对自身业务的理解为每个资产定制专家经验防护规则集,以达到最精准的业务安全防护效果。
客户:日志存储和分析服务适用于哪些业务场景?
安全小二: 满足不低于6个月全量日志存储要求及安全法律法规要求; 支持基于日志的安全和业务事件自动化分析告警,安全态势仪表盘订阅等日常自动化运维; 提供日常安全运维、业务运营以及运营中心的态势实时大屏展示。
如果大家对云盾WAF的开放特点还有其他问题欢迎留言哦,安全小二将为您一一解答^_^
一站式开发者服务,海量学习资源0元起!
阿里热门开源项目、机器学习干货、开发者课程/工具、小微项目、移动研发等海量资源;更有开发者福利Kindle、技术图书幸运抽奖,100%中--》 https://www.aliyun.com/acts/product-section-2019/developer?utm_content=g_1000047140
原文链接
人工智能
2019-03-19 17:20:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
美国时间3月4-8日,国际知名信息安全峰会RSA Conference在美国旧金山开幕, 云安全及云可以为企业提供更可靠的资产管理方式成为大会热点。
此次峰会共吸引全球700多家机构参展,其中近42%为云安全和网络安全相关企业,在所有演讲主题中,云安全超过网络安全和数据安全,成为热门关键词第一。作为全球首家也是唯一一家审计报告覆盖所有C5标准基础要求和附加要求的云服务提供商,阿里云也带去了最核心的云安全产品、行业解决方案、云安全生态。


在RSA经典项目、也是安全行业风向标的Innovation Sandbox(创新沙盒)评选中,线下和云端都可提供资产管理服务的初创公司Axonius夺得冠军,大会认为云上可以提供更好的解决方案、更好的创新技术。
对这一新趋势,阿里云也认为, 整个安全行业对资产管理的重视程度正在提高,而云上资产管理能力在整个企业安全构建中将成为基石且优势明显。


据IDC发布的相关数据显示,到2020年,50%的教育和大型企业将考虑使用VR/AR、大屏幕电子白板、智能手环等产品来提升企业的办公效率。随着越来越多的智能设备进入企业网络,企业资产管理的重要性也逐年增加。
只有做好资产的“看见”能力,才能更好地保障数据安全。在传统IT部署方式下,一次企业资产盘点可能需要花上十个小时,而时间是安全攻防对抗的生命线。 云上具备先天的“看见”能力,能让用户清晰地看到云上资产情况,这在遇到安全事件启动应急响应时尤为重要。
阿里云一直将安全能力建设放在首位。 不仅通过API将用户所有资产甚至配置信息、云产品日志都给到用户,让用户可以清晰地看到云上资产的全部情况;而且针对企业客户构建了一系列资产管理技术栈模型,不但增强了云上安全的看见能力,也增强了自身的安全技术能力,从而保障客户数据安全。
阿里云目前承载着中国超过40%的网站,每天为用户抵御超过36亿次攻击。在IDC发布的《中国云服务提供商安全评估》中,阿里云以在安全上的综合实力和战略前瞻性,位居领导者区间,在安全能力和安全投入上绝对领先。
未来,阿里云还将通过打通云上资产、安全产品、安全生态、基础设施,增强云上、云下的看见能力,构建统一的安全管理中心,实现威胁检测、自动化响应、安全运营优化为一体的闭环体系,保证云上客户的资产安全和数据安全。
作为全球前三、中国第一的云计算服务商,阿里云拥有全球最丰富的云计算产品家族,也是国内最全的人工智能解决方案商。2019年阿里云还获得ITSS最高等级认证,公共云、专有云服务能力达到双一级。

一站式开发者服务,海量学习资源0元起!
阿里热门开源项目、机器学习干货、开发者课程/工具、小微项目、移动研发等海量资源;更有开发者福利Kindle、技术图书幸运抽奖,100%中--》 【阿里云】开年Hi购季,开发者会场

原文链接
本文为云栖社区原创内容,未经允许不得转载。
人工智能
2019-03-19 15:04:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
前几天的3.15晚会上曝光了利用智能机器人,一天打4万个骚扰电话,从而赚取利润的黑色产业链。
阿里的工程师恼了,技术是用来让人们生活变美好的,不是被利用来走向阴暗的。
机器人的问题交给机器人!
工程师们用业余时间开发的AI机器人——“二哈”要登场了~

视频感受一下咱们“二哈”,连女推销员都丝毫没有察觉。
1、 别惹程序员,用机器人对付机器人
研发“二哈”,其实就是阿里的技术人,对日益普遍的骚扰电话很头疼,而且更可气的是,大量骚扰电话是机器自动拨出的,成本越来越低。
这些骚扰电话,甚至还影响到日常工作,会议开着开着,经常被各类电话打断导致会议终中断。于是阿里AI实验室的同学们开始思考着如何用技术的方式解决问题。
阿里AI实验室天猫精灵算法团队,聚集着语音识别、NLP、知识图谱……全链条的技术人才,当技术人聚在一起,那就能搞事情了。
于是他们先以“课余”项目开始,参与的同学都很开心。一方面是解气,另一方面更清楚背后带来的意义。
没想到在今年3.15晚会上,机器人骚扰电话引起如此大关注。
于是团队决定公开最新研发成果,“二哈”也正式从幕后走到台前,一炮而红。
2、 我们要做到真假难辨
“二哈”是这个智能防骚扰电话技术的项目代号。当用户在手机上开通了这项服务,在接到骚扰来电时,用户可以直接转接给机器人接听。
我们都知道哈士奇之所以被喊作“二哈”,就是它欢乐多,工作起来又相当认真。阿里的程序员们,就是希望这个“课余”爱好的项目,给自己带来快乐,也能帮主人扫除骚扰电话的焦虑。
而“二哈”背后,其实主要使用了智能聊天技术。
所谓“智能聊天”,就是要理解用户请求,同时用强大的知识图谱制作聊天的知识点,通过跟用户对话,把知识图谱里的知识灌输给用户,同时也引导用户反馈。
听起来,简单的一段话,要真正实现聊天聊得“真假难辨”却十分不容易。
于是,我们特地请教了阿里达摩院AI实验室语音助手首席科学家聂再清。
原文链接
人工智能
2019-03-19 10:51:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Attention Cluster 模型
视频分类问题在视频标签、监控、自动驾驶等领域有着广泛的应用,但它同时也是计算机视觉领域面临的一项重要挑战之一。
目前的视频分类问题大多是基于 CNN 或者 RNN 网络实现的。众所周知,CNN 在图像领域已经发挥了重大作用。它具有很好的特征提取能力,通过卷积层和池化层,可以在图像的不同区域提取特征。RNN 则在获取时间相关的特征方面有很强的能力。 下载安装命令 ## CPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle ## GPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu
Attention Cluster 在设计上仅利用了 CNN 模型,而没有使用 RNN,主要是基于视频的以下几个特点考虑:
图 1 视频帧的分析
首先,一段视频的连续帧常常有一定的相似性。在图 1(上)可以看到,除了击球的动作以外,不同帧几乎是一样的。因此,对于分类,可能从整体上关注这些相似的特征就足够了,而没有必要去特意观察它们随着时间的细节变化。
其次,视频帧中的局部特征有时就足够表达出视频的类别。比如图 1(中),通过一些局部特征,如牙刷、水池,就能够分辨出『刷牙』这个动作。因此,对于分类问题,关键在于找到帧中的关键的局部特征,而非去找时间上的线索。
最后,在一些视频的分类中,帧的时间顺序对于分类不一定是重要的。比如图 1(下),可以看到,虽然帧顺序被打乱,依然能够看出这属于『撑杆跳』这个类别。
基于以上考虑,该模型没有考虑时间相关的线索,而是使用了 Attention 机制。它有以下几点好处:
1. Attention 的输出本质上是加权平均,这可以避免一些重复特征造成的冗余。
2. 对于一些局部的关键特征,Attention 能够赋予其更高的权重。这样就能够通过这些关键的特征,提高分类能力。
3. Attention 的输入是任意大小的无序集合。无序这点满足我们上面的观察,而任意大小的输入又能够提高模型的泛化能力。
当然,一些视频的局部特征还有一个特点,那就是它可能会由多个部分组成。比如图 1(下)的『撑杆跳』,跳、跑和着陆同时对这个分类起到作用。因此,如果只用单一的 Attention 单元,只能获取视频的单一关键信息。而如果使用多个 Attention 单元,就能够提取更多的有用信息。于是,Attention Cluster 就应运而生了!在实现过程中,百度计算机视觉团队还发现,将不同的 Attention 单元进行一次简单有效的『位移操作』(shifting operation),可以增加不同单元的多样性,从而提高准确率。
接下来我们看一下整个 Attention Cluster 的结构。
整个模型可以分为三个部分:
1. 局部特征提取。 通过 CNN 模型抽取视频的特征。提取后的特征用 X 表示,如公式(1)所示:
(1)。X 的维度为 L,代表 L 个不同的特征。
2. 局部特征集成。 基于 Attention 来获取全局特征。Attention 的输出本质上相当于做了加权平均。如公式(2)所示,v 是一个 Attention 单元输出的全局特征,a 是权重向量,由两层全连接层组成,如公式(3)所示。实际实现中,v 的产生使用了 Shifting operation,如公式(4)所示,其中α和β是可学习的标量。它通过对每一个 Attention 单元的输出添加一个独立可学习的线性变换处理后进行 L2-normalization,使得各 Attention 单元倾向于学习特征的不同成分,从而让 Attention Cluster 能更好地学习不同分布的数据,提高整个网络的学习表征能力。由于采用了 Attention clusters,这里会将各个 Attention 单元的输出组合起来,得到多个全局特征 g,如公式(5)所示。N 代表的是 clusters 的数量。
3. 全局特征分类。 将多个全局特征拼接以后,再通过常规的全连接层和 Softmax 或 Sigmoid 进行最后的单标签或多标签分类。
用 PaddlePaddle 训练 Attention Cluster
PaddlePaddle 开源的 Attention Cluster 模型,使用了 2nd-Youtube-8M 数据集。该数据集已经使用了在 ImageNet 训练集上 InceptionV3 模型对特征进行了抽取。
如果运行该模型的样例代码,要求使用 PaddlePaddle Fluid V1.2.0 或以上的版本。
数据准备: 首先请使用 Youtube-8M 官方提供的链接下载训练集和测试集,或者使用官方脚本下载。数据下载完成后,将会得到 3844 个训练数据文件和 3844 个验证数据文件(TFRecord 格式)。为了适用于 PaddlePaddle 训练,需要将下载好的 TFRecord 文件格式转成了 pickle 格式,转换脚本请使用 PaddlePaddle 提供的脚本 dataset/youtube8m/tf2pkl.py。
训练集:http://us.data.yt8m.org/2/frame/train/index.html
测试集:http://us.data.yt8m.org/2/frame/validate/index.html
官方脚本:https://research.google.com/youtube8m/download.html
模型训练: 数据准备完毕后,通过以下方式启动训练(方法 1),同时我们也提供快速启动脚本 (方法 2)
# 方法 1
# 方法 2
用户也可下载 Paddle Github 上已发布模型通过--resume 指定权重存放路径进行 finetune 等开发。
数据预处理说明 : 模型读取 Youtube-8M 数据集中已抽取好的 rgb 和 audio 数据,对于每个视频的数据,均匀采样 100 帧,该值由配置文件中的 seg_num 参数指定。
模型设置 : 模型主要可配置参数为 cluster_nums 和 seg_num 参数。其中 cluster_nums 是 attention 单元的数量。当配置 cluster_nums 为 32, seg_num 为 100 时,在 Nvidia Tesla P40 上单卡可跑 batch_size=256。
训练策略:
采用 Adam 优化器,初始 learning_rate=0.001
训练过程中不使用权重衰减
参数主要使用 MSRA 初始化
模型评估 :可通过以下方式(方法 1)进行模型评估,同样我们也提供了快速启动的脚本(方法 2):
# 方法 1
# 方法 2
使用 scripts/test/test_attention_cluster.sh 进行评估时,需要修改脚本中的--weights 参数指定需要评估的权重。
若未指定--weights 参数,脚本会下载已发布模型进行评估
模型推断: 可通过如下命令进行模型推断:
模型推断结果存储于 AttentionCluster_infer_result 中,通过 pickle 格式存储。
若未指定--weights 参数,脚本会下载已发布模型 model 进行推断
模型精度: 当模型取如下参数时,在 Youtube-8M 数据集上的指标为:
参数取值:
评估精度:
>> 访问 PaddlePaddle 官网, 了解更多相关内容 。 下载安装命令 ## CPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle ## GPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu
人工智能
2019-03-18 21:57:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
上线不到一年的AI开放平台——百度AI Studio又有大动作!这回,它把目光对准了全中国的大学。 下载安装命令 ## CPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle ## GPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu
3月7日,AI Studio在个人版的基础上,推出了专为高校教师和学生定制的教育版,提供教学项目、教学互动、AI在线实训环境、教学管理后台,力求一站式解决高校在开展人工智能教育过程中,老师上课难、学生实践难、教学过程跟踪难的问题。
云上开发,AI Studio有多硬核?
于去年6月推出的AI Studio 是百度推出的一站式开发平台,集合了AI教程、代码环境、算法算力和数据集,并为用户提供在线云计算编程环境,不需要用户下载安装、环境配置和依赖包等繁琐步骤,就可以开展深度学习项目。
AI Studio个人版
本次全新推出的AI Studio教育版则在原有平台的基础上,深度理解高校人工智能教育场景,打造新时代AI教育模式。凭借一站式教学服务、海量业内最新教案项目、独家线上高性能教学实践环境、稳定服务保障四大特性,AI Studio教育版可以将学生、教师和教学材料、实践环境连接起来,高效解决传统AI教育面临的理论讲解枯燥、学生积极性不高、老师教学资源少、无法进行实战练习等一系列难题。
高校及其他教育机构的教师可以通过教学班级管理、学生管理、教学专区、班级信息四个板块进行个性化设置,实现全线上AI教学;学生则可以通过身份认证和项目学习两大版块构建属于自己的AI课程学习规划。
AI Studio教育版基本流程示意图
与其他云平台有偿服务不同的是,AI Studio教育版提供包括计算资源、空间资源、项目托管、视频教程在内的所有服务全部免费,为广大师生减负降压。
死磕教育场景,“AI”上智能教育
百度推出AI Studio并非心血来潮。事实上,百度从没有放松过对高校人工智能教育赋能的尝试,此次推出AI Studio教育版更是直接从基础层面重塑了AI教育模式,在提供教学案例、推动学生实践、跟踪教学成果方面表现尤为突出。
针对高校缺乏教学案例的痛点,AI Studio教育版提供百度官方推荐的全套教学课程资料、实践项目,着力解决教师上课难的问题。授课教师只需在教学专区的教学内容版块点击添加Notebook,就可以从百度“AI学习项目”“我的项目”目录选择相应案例添加到课程当中。基于老师添加的教学项目,学生可以在项目学习板块自主选择兴趣项目,免费使用该平台提供的线上开发资源,在笔记本上跑模型,做开发,使其真正脱离客观条件的制约,自由实践。
AI Studio教育版上提供了丰富的教学实践案例
而在该版本的众多功能当中,实现教学过程“全天候”跟踪的项目统计功能被研发团队寄予厚望。通过项目统计,授课教师可以实时跟踪学生项目实践/作业/测试完成的情况,并进行评分,实现了师生间的教学互动,让教师对班级的整体情况有更加全面的把控。
项目统计功能实现教学“全天候”跟踪
在高校教学场景当中,老师可以借助AI Studio教育版实现课前资料推送、课中互动、课后测验整个教学过程的全覆盖,让理论讲解与实战练习有机结合,显著提升教学效果。同时,该版本还帮助学生完成了课程翻转,实现课前预习、课中解惑、课后复习,在夯实理论基础的同时获得了更多的实践机会。
厚积薄发,AI Studio抢滩高校开学季
百度作为一家企业,想要深刻理解教育场景,并基于这些场景给出科学的解决方案并不容易。AI Studio教育版上线的背后,是百度多年来与高校交流合作的经验积累和对AI技术全面掌控的成果。
在百度众多的校企合作项目中,全国深度学习师资培训班直接推动了AI Studio教育版的诞生。自去年5月起,百度先后举办了三期全国深度学习师资培训班,培训高校教师超300人次。活动当中,多位参训教师提出希望把百度的开源平台引入实际教学当中,并提出诸多基于教学场景的改进建议。这成了催生AI Stduio教育版的原动力。
从去年12月第三期师资培训班需求成形到3月5日成功上线,AI Studio教育版研发团队放弃春节假期,历时3月,终为全国高校师生送上了一份春季学期的开学礼物。
2018新工科产学研联盟深度学习师资培训班第三期参训教师与嘉宾合影
今年的政府工作报告则首次提出“智能+”的概念,进一步强调人工智能的在产业发展当中的重要作用。作为一家科技企业,百度死磕高校教育场景的背后,是对人工智能人才的珍视。在拥抱国家战略的过程当中,百度基于自身技术优势,向高校开源赋能,协同培养人工智能人才,践行属于自己的责任。
AI Studio教育版的上线,为我国人工智能教育改革提出了新思路,创造了新模式,使得校企之间实现资源互通、优势互补,并且直接打通了校企之间人才对接的瓶颈,为人工智能人才培养提供了经典范例。同时,百度也期待更多高校的加入,在更新、完善现有平台生态的同时,让中国AI在校园内真正普及,播撒更多AI种子,持续推动我国人工智能技术的发展。
>> 访问 PaddlePaddle 官网, 了解更多相关内容 。 下载安装命令 ## CPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle ## GPU版本安装命令 pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu
人工智能
2019-03-18 19:39:00
「深度学习福利」大神带你进阶工程师,立即查看>>> import numpy as np from numpy import exp from sklearn import datasets def sigma(z): if z>=0: return 1/(1+exp(-z)) else: return exp(z)/(1+exp(z)) class Net: def __init__(self, X, Y, num): # num 是隐藏层神经元个数 self.num = num self.B = np.zeros(num) self.X = X self.Y = Y # self.wB = np.ones(num+1) #隐藏层和输出层间的连接权和阈值 np.random.seed(2) self.wB = np.random.random(num+1) #隐藏层和输出层间的连接权和阈值 # self.WX = np.array([np.ones(X.shape[1]+1)*0.01 for i in range(num)]) #输入层和隐藏层间的连接权和阈值 self.WX = np.array([np.random.random(X.shape[1]+1)*0.01 for i in range(num)]) #输入层和隐藏层间的连接权和阈值 def cal_g(self, Xi, yi): # print(Xi) # 计算 输出层到隐藏层的 梯度变量, Xi 是一个输入 # 计算 隐藏层的值 for i in range(self.num): self.B[i] = sigma(np.dot(np.append(Xi, np.array([-1])).T, self.WX[i])) # 使用tanh当隐层激活函数,可比sigma更快收敛 # self.B[i] = np.tanh(np.dot(np.append(Xi, np.array([-1])).T, self.WX[i])) # print(self.B[i]) # 计算 输出层的值 y = sigma(np.dot(np.append(self.B, np.array([-1])).T, self.wB)) g = (yi-y)*y*(1-y) self.g = g # print(f"g:{g}") return g def cal_e(self, Xi, yi): # 计算 隐藏层到输入层的 梯度变量 # 先计算g if not self.g: g = self.cal_g(Xi, yi) else: g = self.g ret = [] for i in range(self.num): b = self.B[i] e = b*(1-b)*g*self.wB[i] ret.append(e) self.e = ret def learn(self, pace=0.1, max_num=300): r = self.Y.shape[0] for j in range(max_num): for i in range(r): Xi = self.X[i] yi = self.Y[i] self.cal_g(Xi, yi) self.cal_e(Xi, yi) g = self.g es = self.e self.wB += pace*g*np.append(self.B, np.array([-1])) # 更新 隐层 和输出层之间的权值 for k in range(self.num): self.WX[k] += pace*es[k]*np.append(Xi,np.array([-1])) return True def __call__(self, Xi): for i in range(self.num): # self.B[i] = np.tanh(np.dot(np.append(Xi, np.array([-1])).T, self.WX[i])) self.B[i] = sigma(np.dot(np.append(Xi, np.array([-1])).T, self.WX[i])) # 计算 输出层的值 y = sigma(np.dot(np.append(self.B, np.array([-1])).T, self.wB)) return 1 if y>=0.5 else 0 def test(): iris = datasets.load_iris() def get_i(n): while n: yield n%2 n = n>>1 def get_t(n): t = [] for i in get_i(n): t.append(i) while len(t)<4: t.append(0) return t X = np.array([(1,1),(1,0),(0,0),(0,1)]) for Y in np.array([get_t(n) for n in range(15)]): net = Net(X, Y, 2) net.learn(max_num=30000) a = np.array([net(np.array(x)) for x in ([1,1],[1,0],[0,0],[0,1])]) print(f"Y:{Y}\ta:{a}\t{all(a==Y)}") test()
人工智能
2019-03-21 13:14:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
简介
给定一个包含上千万用户的社交网络,我们会实现一个MapReduce、Spark程序,在所有用户对中找出“共同好友”。
令 $$ {U_1,U_2,...,U_n} $$ 为包含一个所有用户列表的集合。我们的目标是为每个$(U_i,U_j)$对$i\ne j$找出共同好友。
我们本章提出3个解决方案: MapReduce/Hadoop解决方案,使用基本数据类型 Spark解决方案,使用弹性数据集RDD。
1、共同好友的概念
如今大多数社交网络网站都提供了有关的服务,可以帮助我们与好友共享信息、图片和视频。
有些网站树森之还提供了视频聊天服务,帮助你与好友保持联系。根据定义,“好友”是指你认识、喜欢和信任的一个人。
比如我们QQ好友列表,这个列表上好友关系都是双向的。如果我是你的好友,那么你也是我的好友,注意这个特点,我们的程序中运用了这个特点,将这种关系进行合并求解交集,即可得到A,B的共同好友。
有很多办法可以找到共同好友: 使用缓存策略,将共同好友保存在一个缓存中(redis、memcached) 使用Mapreduce离线计算,每隔一段时间(例如一天)计算一次每个人的共同好友并存储这些结果;
1、POJO共同好友解决方案
令${A_1,A_2,...A_n}$是$user_1$的好友集合,${B_1,B_2,...,B_n}$是$user_2$的好友集合,那么,$user_1,user_2$的共同好友集合就可以定义为 $$ A \cap B $$ 即两个集合的交集。
POJO的简单实现如下所示: package com.sunrun.movieshow.algorithm.friend; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class POJOFriend { public static Set intersection(Set A, Set B){ if(A == null || B == null){ return null; } if(A.isEmpty() || B. isEmpty()){ return null; } Set result = new HashSet<>(); result.addAll(A); result.retainAll(B); return result; } public static void main(String[] args) { Set A = new HashSet<>(); Set B = new HashSet<>(); A.add("A"); A.add("B"); A.add("C"); B.add("B"); B.add("C"); B.add("D"); System.out.println(intersection(A,B)); /** * [B, C] */ } }
2、MapReduce解决方案
映射器接受一个$(k_1,v_1)$,其中$k_1$是一个用户,$v_1$是这个用户的好友列表。
映射器发出一组新的$(k_2,v_2)$,$k_2$是一个$Tuple2(k1,f_i)$,其中$f_i \in v_1$,即会迭代所有的好友列表和$k_1$进行两两组合。
归约器的key是一个用户对,value则是一个好友集合列表。reduce函数得到所有好友集合的交集,从而找出$(u_i,u_j)$对的共同好友。
至于在Mapper过程中的数据传输,会关联到数组类型,我们有两个方案:
1、依然使用文本形式,在Driver节点进行解析;
2、如果你的信息需要解析为非String,例如Long等,可以使用ArrayListOfLongsWritable类。
他是一个实现了Hadoop串行化协议的类,我们不必自己去实现这些接口,可以直接从第三方组件里面抽取使用 edu.umd cloud9 1.3.2
该组件包含了丰富的实现了hadoop序列化的协议提供使用,比如 PairOfStrings 以及 ArrayListOfLongWritable 等。
2.1、Mapper package com.sunrun.movieshow.algorithm.friend.mapreduce; import edu.umd.cloud9.io.pair.PairOfStrings; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.io.Writable; import org.apache.hadoop.mapreduce.Mapper; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class FriendMapper extends Mapper { private static final Text KEY = new Text(); private static final Text VALUE = new Text(); // 获取朋友列表 static String getFriends(String[] tokens) { // 不可能再有共同好友 if (tokens.length == 2) { return ""; } StringBuilder builder = new StringBuilder(); for (int i = 1; i < tokens.length; i++) { builder.append(tokens[i]); if (i < (tokens.length - 1)) { builder.append(","); } } return builder.toString(); } // 使key有序,这里的有序只的是key的两个用户id有序,和整体数据无关 static String buildSortedKey(String user, String friend) { long p = Long.parseLong(user); long f = Long.parseLong(friend); if (p < f) { return user + "," + friend; } else { return friend + "," + user; } } @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String[] tokes = value.toString().split(" "); // user String user = tokes[0]; // value VALUE.set(getFriends(tokes)); // rescue keys for (int i = 1; i < tokes.length ; i++) { String otherU = tokes[i]; KEY.set(buildSortedKey(user,otherU)); context.write(KEY,VALUE); } } }
2.2、Reducer package com.sunrun.movieshow.algorithm.friend.mapreduce; import org.apache.commons.lang.StringUtils; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; import java.util.*; public class FriendReducer extends Reducer { static void addFriends(Map map, String friendsList) { String[] friends = StringUtils.split(friendsList, ","); for (String friend : friends) { Integer count = map.get(friend); if (count == null) { map.put(friend, 1); } else { map.put(friend, ++count); } } } @Override protected void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException { Map map = new HashMap(); Iterator iterator = values.iterator(); int numOfValues = 0; while (iterator.hasNext()) { String friends = iterator.next().toString(); if (friends.equals("")) { context.write(key, new Text("[]")); return; } addFriends(map, friends); numOfValues++; } // now iterate the map to see how many have numOfValues List commonFriends = new ArrayList(); for (Map.Entry entry : map.entrySet()) { //System.out.println(entry.getKey() + "/" + entry.getValue()); if (entry.getValue() == numOfValues) { commonFriends.add(entry.getKey()); } } // sen it to output context.write(key, new Text(commonFriends.toString())); } }
3、Spark解决方案 package com.sunrun.movieshow.algorithm.friend.spark; import avro.shaded.com.google.common.collect.ImmutableCollection; import com.google.common.collect.Sets; import com.sunrun.movieshow.algorithm.common.SparkHelper; import org.apache.spark.api.java.JavaPairRDD; import org.apache.spark.api.java.JavaRDD; import org.apache.spark.api.java.JavaSparkContext; import scala.Tuple2; import shapeless.Tuple; import java.util.*; /** * 共同好友的Spark解决方案 * 输入: * [root@h24 ~]# hadoop fs -cat /friend/input/* * A B C D E * B A C D * C A B D E * D A B C * E A C * F A * 即第一列代表当前用户,后面的数据代表其好友列表。 * * 输出 * (A,B) => C,D * 两个好友之间的公共好友。 */ public class FriendSpark { // 构建有序key,避免重复 static Tuple2 buildSortedKey(String u1, String u2){ if(u1.compareTo(u2) < 0){ return new Tuple2<>(u1,u2); }else{ return new Tuple2<>(u2,u1); } } public static void main(String[] args) { // 1.读取配置文件 String hdfsUrl = "hdfs://10.21.1.24:9000/friend/"; JavaSparkContext sc = SparkHelper.getSparkContext("CommonFriend"); JavaRDD rdd = sc.textFile(hdfsUrl + "input"); // 2.解析内容 /** * A B C * ((A,B),(B,C)) * ((A,C),(B,C)) */ JavaPairRDD, List> pairs = rdd.flatMapToPair(line -> { String[] tokes = line.split(" "); // 当前处理的用户 String user = tokes[0]; // 该用户的好友列表 List friends = new ArrayList<>(); for (int i = 1; i < tokes.length; i++) { friends.add(tokes[i]); } List, List>> result = new ArrayList<>(); // 算法处理,注意顺序,依次抽取每一个好友和当前用户配对作为key,好友列表作为value输出, // 但如果该用户只有一个好友的话,那么他们的共同好友应该设置为空集 if (friends.size() == 1) { result.add(new Tuple2<>(buildSortedKey(user, friends.get(0)), new ArrayList<>())); } else { for (String friend : friends) { Tuple2 K = buildSortedKey(user, friend); result.add(new Tuple2<>(K, friends)); } } return result.iterator(); }); /** * pairs.saveAsTextFile(hdfsUrl + "output1"); * ((A,B),[B, C, D, E]) * ((A,C),[B, C, D, E]) * ((A,D),[B, C, D, E]) * ((A,E),[B, C, D, E]) * ((A,B),[A, C, D]) * ((B,C),[A, C, D]) * ((B,D),[A, C, D]) * ((A,C),[A, B, D, E]) * ((B,C),[A, B, D, E]) * ((C,D),[A, B, D, E]) * ((C,E),[A, B, D, E]) * ((A,D),[A, B, C]) * ((B,D),[A, B, C]) * ((C,D),[A, B, C]) * ((A,E),[A, C]) * ((C,E),[A, C]) * ((A,F),[]) */ // 3.直接计算共同好友,步骤是group以及reduce的合并过程。 JavaPairRDD, List> commonFriends = pairs.reduceByKey((a, b) -> { List intersection = new ArrayList<>(); for (String item : b) { if (a.contains(item)) { intersection.add(item); } } return intersection; }); commonFriends.saveAsTextFile(hdfsUrl + "commonFriend"); /** * [root@h24 ~]# hadoop fs -cat /friend/commonFriend/p* * ((A,E),[C]) * ((C,D),[A, B]) * ((A,D),[B, C]) * ((C,E),[A]) * ((A,F),[]) * ((A,B),[C, D]) * ((B,C),[A, D]) * ((A,C),[B, D, E]) * ((B,D),[A, C]) */ } }
人工智能
2019-03-21 11:01:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
https://www.openml.org/search?type=data
人工智能
2019-03-20 21:48:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
活动当天,百度AI技术生态部总经理喻友平,就百度大脑平台与生态进行了全面的详解,同时展示了百度大脑开放平台Q1核心升级内容,包括语音技术、视觉技术、自然语言处理、知识图谱等通用AI能力的新近推出,以及开源深度学习框架方面的优化升级,更有多个应用场景案例与大家分享,可谓干货满满,广受前来参加活动的开发者与媒体们欢迎与称赞。
1 PaddlePaddle:用深度学习赋能智能+的方方面面
1、业界首个视频分类模型库: 新增视频模型库,提供5个视频分类经典模型以及适合视频分类任务的通用骨架代码,用户可一键式高效配置模型完成训练和评测。视频理解权威竞赛ActivityNet - Kinetics视频动作识别任务冠军方法stNet的resnet50版本开源实现。
2、基于PaddlePaddle的BERT多机多卡和混合精度训练。 新增支持NLP语义表示BERT模型,支持多机多卡训练,支持混合精度训练,训练速度对比主流实现提升50%+,提供完整部署示例。
3、分布式训练性能大幅提升: 大规模稀疏参数服务器Benchmark发布, CPU多机异步训练发布显著提升点击率预估任务IO吞吐的built-in reader,多机多卡训练性能多方面提升。
并推出业界领先的深度强化学习框架PARL1.0。据喻友平介绍,PARL曾在NeurIPS 2018 夺冠。具有高灵活性和可扩展性,支持可定制的并行扩展,覆盖DQN、DDPG、PPO、A3C等主流强化学习算法。通过8块GPU拉动近20000个CPU节点运算,将近5个小时迭代一轮的PPO算法加速到不到1分钟。
如今,百度PaddlePaddle已经广泛应用于农业、林业、工业、零售、人力、制造、石油、通讯、地产、汽车等多个行业领域,与合作伙伴一起帮助越来越多的行业完成向“智能+”的升级转变。
2 语音方向:首次开放搭载国际领先的注意力模型的语音能力:语音识别极速版
根据喻友平介绍,目前百度大脑语音开放能力包括语音唤醒、语音识别、语音合成等通用能力,还包括即将推出的语音识别自训练平台、软硬一体的语音开发套件以及各种场景方案。
1月的百度输入法探索版发布会上,首次发布了领先国际的语音技术:在线语音领域全球首创的流式多级截断注意力模型SMLTA「Streaming trancated multi-layer attention」,这是首次在大规模语音识别工业界采用注意力(attention)模型,在百度输入法产品发布后,惊艳的语音输入体验得到了业界的一致好评。基于以上成果持续进行更多创新,提升识别率的同时又大幅优化解码速度。百度大脑语音方向首次将这一系列技术创新整合为语音能力对外开放:“语音识别极速版”,拥有更快的响应速度,相对识别准确度提升15%,为开发者带来更极致的识别体验。
此项语音能力在API调用方式下,实时率小于0.1,意味着5s的音频不到500ms即可完成识别过程,极大减少了识别音频所需的耗时,提升了语音交互的响应体验。在近距离安静环境下,识别准确率可达到98%,同时支持略带口音、童声、耳语的识别,使语音识别应用更加广泛。多平台的SDK也即将推出,使APP、服务器端更可实时识别,应用这一领先技术。目前,每个开发者账户将赠送5W次免费调用量,针对新能力的使用者,也即将推出一系列赠送及优惠活动。
同时,近场语音识别升级了预置语义解析。预置场景由35个升级为51个,包括天气、航班、电话、电影播放、页面屏幕控制、电视剧、美食、手机设置、通用录、提醒、短信、故事等,语义解析效果全面优化,80%优于原有解析结果。
不仅如此,还有一些新品即将上线。如:语音识别自训练平台,支持自动评估选出最好的基线模型,仅上传业务场景文本语料即可训练语言模型,零代码自助训练专属的语音识别模型,极大地方便语音开发者提升所在业务场景的识别准确率,满足业务上的语音识别需求。另外,远场语音开发套件也即将上架售卖,可快速进行远场识别开发评估,此套件应用于机器人、儿童故事机、家电、车载设备等硬件。同时还将开放离线合成,以及推出更多音库。
3 视觉方向:从车到人再到“证” 用AI都能看得清
在百度大脑开放日,喻友平还介绍了视觉方向更新升级的四方面内容,包括OCR、车辆分析、人脸人体以及图像识别。
1、首先,在极大便捷工作的OCR方面:1.新增了卡证OCR 4个新能力:户口本OCR、出生医学证明OCR、港澳通行证OCR、台湾通行证OCR,总数达到9种;
2、 新增票据OCR 4个新能力:行程单OCR、保单识别OCR、通用机打发票OCR,定额发票OCR,总数达到9种;
3. 汽车场景3个新能力:车辆VIN OCR、机动车销售发票OCR、车辆合格证OCR,总数达到6种。这些OCR新能力在关键字段的准确率均在90%以上,并有多项是业界首次平台化开放。至此,OCR产品全系列共34款,实现卡证、票据、文档、汽车全场景覆盖。
同时,对已有的OCR能力也进行了功能升级:表格识别:支持合并单元格、无表格线等复杂样式;iOCR 自定义模版文字识别:支持列宽不固定、有合并单元格的表格样式的定制识别;驾驶证识别:支持驾驶证副页的识别。
其次,在车辆分析方面,推出全新系列服务:包括车辆检测、车流统计、车辆属性分析和外观损伤识别。其中,车辆检测,通过识别图像中的所有机动车辆(包含小汽车、卡车、巴士、摩托车、三轮车),返回每辆车的类型和坐标位置,并对每类车辆分别计数,可应用于违章停车监测和智能停车场。
车辆检测
车流统计,则根据视频抓拍图片序列,进行车辆检测和追踪,识别各类车辆(包括小汽车、卡车、巴士、摩托车、三轮车)在指定区域内的驶入/驶出情况,实现动态车流统计,可应用于实时监控交通道路、卡口的车流量,自动统计不同时段各类车辆的进出数量,分析路口、路段的交通状况,为交通调度、路况优化提供精准参考依据。而车辆属性分析和外观损伤识别两项服务,也即将开放,尽请期待。
车辆属性识别
在人脸人体识别方面,新发布了情绪识别,可以准确识别7类情绪:生气、害怕、厌恶、高兴、悲伤、惊讶、无情绪。此项技术可应用于幼儿园安全监控等场景,通过监控孩子的心理状态,判断教师和幼儿是否有异常状况,从而保障幼儿安全、及时预警并参与辅导等。同时人脸融合以及手部关键点将在3月推出。此外还有2项功能全新升级,包括:人脸检测快速检测人脸并返回人脸框位置、定位五官与轮廓关键点数量,从72个增加至150个;新增2种手势,共24种常见手势,整体识别率在90%以上,使得手势识别更丰富、更准确;而即将上线的更高进精度的人像分割,可应用于人像美图、影视后期等场景。
而在图像识别方面,新增红酒识别和地标识别这2个新能力。通过红酒识别,用户只需要对着红酒标签拍照,系统就能自动识别红酒的品牌和名称,目前可识别数十万种国内外红酒,识别准确率98%以上,从法国波尔多到中国张裕,商品信息都能得到准确关联,可以轻松为用户提供参考和商品推荐。而地标识别则能够精准识别约5万中外著名地标、景点,准确率高达94%以上。用户只需要拍摄包含国内外著名景点、地标的照片,系统就能自动生成足迹、图文博客等有意思的交互内容,提升用户旅游体验。
同时,开放日现场还宣布,百度大脑即将上线邀测钱币识别功能。该功能可以精准识别中外钱币,支持数百类币种、数千种面额,识别准确率98%以上,不仅能够提升金融机构货币兑换的效率,也能让“外币骗局”无处藏身。
从红酒到地标再到钱币,目前百度大脑的图像识别种类已经多达11种。
4 语言及知识:能为你写诗,还能读懂你的情绪
百度大脑语言及知识方向能力集,共包括语言处理应用平台、语言处理应用技术、语言处理基础技术、知识理解以及知识图谱。而此次开放日的更新亮点是,语言处理应用技术、知识理解以及智能写作平台。
在语言处理应用技术方面,推出新能力:1.文本纠错,识别文本中有错误的片段,进行错误提示并给出正确的建议文本内容;2.新闻摘要,对新闻内容进行全面的语义理解与分析,自动抽取新闻文本中的关键信息并按指定长度生成摘要,可应用于热点新闻聚合、新闻推荐、语音播报、APP消息Push等场景;3.智能写诗,用户只需要输入任意主题词(如公司名、节气名),机器便可自动生成融合了该主题词的诗词;4.智能春联,用户输入任意主题词(如自己的名字),机器可自动生成融合了该主题词的春联,可以应用在企业互动营销、APP春节互动活动; 5.对话情绪识别,可以针对一段对话文本,自动识别出当前会话者所表现出的情绪类别;
在知识理解方面,则推新能力:1.作文检索,有数万篇作文范文,可支持按文体、字数、年级、常见主题等进行查询检索,可应用在少儿教育产品(如学习机)、图书馆等场景;2.知识问答,可提供娱乐、人物、教育、影视、综艺、动漫、小说、文学作品等垂类的问答能力,以及日期历法、年龄差、算数、时间时区差等推理计算能力,可应用于智能音箱、儿童故事机、泛娱乐产品等场景。
同时,不久后,智能写作平台也将上线,将从素材上为创作者提供工具、帮助找到灵感,提升创作者的写作效率和产出质量,降低写作成本。

在百度大脑首场开放日,除了有以上多项核心的技术更新、能力升级、新品推出外,百度大脑在AI市场正式上架4款硬件产品,感兴趣的开发者都可以在PC 端访问百度AI 市场进行选购。同时推出百度大脑新品体验师计划,希望可以在帮助开发者成长的同时,推动百度大脑的进化。
其实,百度大脑一直致力于构建开放的技术生态,已成其多年技术积累和业务实践的集大成者。截至目前,百度大脑已经开放了近160项AI能力,平台上开发者数量超过100万,开放能力覆盖语音、视觉、自然语言处理、机器学习等全面AI技术。
此次开放日活动,百度大脑诚邀众多开发者、技术媒体、行业KOL共同参与,了解体验百度大脑AI技术,共同探讨AI在开发、落地应用过程中遇到的实际问题,一起助力AI发展加速度。其实,除了此次的开放日活动外,百度大脑还推出了“月度更新计划”,每个月一次的产品与技术更新,旨在助力企业和个人开发者智能前行,紧跟社会需求,这足以让广大企业和开发者们对百度大脑充满信心,对我国未来人工智能的发展充满期待。
人工智能
2019-03-20 20:59:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
前言:
如今的科技在各个方面的发展都非常的迅速,越来越多“不切实际”的幻想也在被实现!而作为现代人信息获取以及沟通需求最为方便快捷的路径-智能语音,这条路就摆在我们面前。
演讲嘉宾:
盛京,阿里云达摩院-机器智能技术专家
达摩院语音组成立于2014年,具有语音识别、语音合成、声纹识别、自然语言处理、语音交互等等的能力。
以下内容根据演讲嘉宾视频分享以及PPT整理而成。
本次主要内容分为四部分:
一.公共云方案
二.智能语音本地化部署方案
三.智能互动大屏
四.语音自学习平台
一、公共云方案
在公共云方面,服务于集团34个BU,107个业务,包括手淘、支付宝、菜鸟、钉钉、口碑、高德、UC、优酷土豆、天猫精灵等;除了内部外,还有映客直播、一号互联等用户。
从2014年手淘上线后,我们的语音识别覆盖了各种各样的场景。这里面有单纯的手机APP,也有车载,包括18年的时候,包括地铁通过语音购票、甚至最新款的汽车。
给大家具体介绍下,服务于客服方面,我们是如何利用智能语音能力的?
在智能客户领域,我们两个最典型的的案例就是支付宝95188和菜鸟的1518。
支付宝是一个呼入的场景,他是一个电话的、智能的客服。大家如果有打过支付宝电话的一定知道,打完之后,电话另一方会说“请用一句话来描述您的问题”。这时候您可以说:“我的密码忘了”,这时候会有机器人和你对话,告诉你具体的方法。这个就是支付宝电话客服的应用场景。
那么呼出场景,就是菜鸟的智能语音助手,去年双11的时候,我本人就接到过菜鸟打来的电话,他会说:先生,您的某某快递放在小区的蜂站了。如果您说可以,他会礼貌的挂机;如果您说不可以的,他会问你:先生,您什么时候在家,我会把快递给您送过去等等。
这两个应用都节省了大量的人力,在双11时,支付宝智能客服自主率达到了97%;菜鸟机器人替200W快递员打电话。在过去11快递员工作主要就是打电话,现在通过菜鸟助手,就能解决绝大多数问题。
二、智能语音本地化部署方案
除了刚刚介绍的公共云的情况,我们在本地化部署上也有很多应用的场景。
我们提供的主要是一套软件,有能力的开发公司可以把我们语音的能力集成到你们的产品中,这样我们可以共同深入打造各行各业各个场景下的解决方案。
我们提供的能力包括 语音识别、语音合成、MRCP、防串音、最重要的还有语音自学习平台。
我们最主要的是聚焦于语音的核心能力,紧靠行业伙伴,我们是一起打造产品的。
我们和友商的区别主要是:友商做语音产品都是端对端的,所有东西都是自己做;而我们只做最核心的,语音识别或者语音合成。然后把能力开放出来,让合作伙伴基于这样的能力来做各种各样的应用。
我们本地化部署方案的标杆是有: 智慧法院的一个解决方案,目前我们深度合作了法院领域头部的ISV,包括了华宇、云嘉等等。
我们标杆案例有 浙江高院、福建高院 等等,覆盖了300家法院,有超过1万家法庭应用了我们语音识别。
这是我们在法院的一些场景,所做的一些事情。同时全国的几大互联网法院,包括第一家杭州互联网法院,北京、广州互联网法院,用的都是我们的语音识别。
在智能客服领域,我们联合阿里小蜜,和ISV为中国移动、中国平安做了智能电话机器人、外呼以及金牌话术。
金牌话术还是要再提一下,在客服领域,不同人的交流沟通能力也不一样的,反馈到结果上就是有的人业绩比较好,有的人差一些。我们金牌话术要做的就是:基于客服和客户的聊天,来把沟通弄技巧挖掘出来。每当你和客户交流的时候,就会提示你应该怎么说,应该做什么样的引导。
三、智能互动大屏
除了刚才介绍的客服和司法,我们还有 达摩院全球首创多模态语音交互方案 ,能够实现在强噪音环境下的免唤醒人机交互。
比如说在公共空间,地铁购票、肯德基点餐,都能够通过我们这套解决方案实现人机交互,我们这个产品的优势,就是强噪音语音环境下的语音识别、同时免唤醒、以及长句子的流失理解。
这套语音交互产品模式就是:我们提供软硬件一体的套件,再加上定制的外壳,我们有一个官方标准的,合作伙伴也可以根据各种需求来定制,之后我们就可以对接到客户的系统里面。
这时候就能有各行各业的应用,比如对接客户的支付系统。图书管理系统、导航系统。
这套方案的标杆案例就是: 上海地铁语音售票机。
• 2018年3月已正式落地上海南站和汉中路地铁站
• 全球第一台地铁语音售票机
• 在地铁真实嘈杂环境下语音识别准确率超过96%
上海地铁语音售票机介绍视频点击播放
四、语音自学习平台
最后我们来介绍下— 语音自学习平台 。
之所以提供语音自学习平台,是因为我们在与客户接触中,听到客户很多对语音识别的建议。首先语音识别是一个非标输出的软件,部署到客户现场的时候,可能由于麦克风、口音等等,导致识别率不好;或者领域不匹配,比如客户有一些专业的用语,我们自己的模型可能覆盖不到。
所以我我们提供了语音自学习平台。独特优势主要在于:可以通过自助来添加语料的方式来进行优化,可以输入词、句子、篇章,具备分钟级的训练速度,而且操作很简单,可以一键式完成。
语音自学习平台主要包括三部分:
泛热词
北京女子图片→北京女子图鉴
类热词(人名、地名等)
原告以不应选公司→原告与布衣轩公司
我们可以看到,如果你不做任何的优化,很容易出现各种混淆错误。
定制化语言模型
提供的是整个的篇章,比如说有些公司有内部的材料,比如说客服行业,我们可能有一些产品介绍、文档之类的,都是长篇的文本,我们就可以定制化语言模型来优化。
以上就是我们今天讲的主要内容,大家如果有兴趣可以持续关注我们!
下面是我们的QA环节:
1. 语音产品收费
公有云都是支持免费试用的,按照文档一步步操作,就可以创建自己的语音识别程序。
点击试用
2. 我们语音有哪些类型?
a) 实时语音识别:实时反馈结果
b) 一句话识别:应用在搜索的场景下
c) 录音文件转写:相较于实时语音识别,速度很快
3.教育行业有哪些语音场景?
在过去,我们无法落实每堂课的知识点,如果有了智能语音,我们可以把老师讲的内容全部转成文字,再通过一定的质检规则来判断老师是否做到位了;同时类似于儿童学英语行业,口语评测之类的也会有一些需求。
相关链接:
PPT地址: 敬请期待
产品地址: https://ai.aliyun.com/nls
上海云栖大会主论坛孙权现场直播连线上海南站
点击观看语音点餐机介绍视频
点击观看真机演示视频
原文链接
人工智能
2019-03-20 18:10:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
简介
这一章节我们讲解马尔科夫模型。给定一组随机变量(如顾客最近的交易日期),马尔科夫模型只根据前一个状态(前一个最近交易日期)的分部指示该变量最近的分布。
1、马尔科夫链基本原理
令 $$ S = {S_1,S_2,...,S_n} $$ 是一个有限的状态集,我们希望得到如下的结果: $$ P(S_n|S_{n-1},S_{n-2},...,S_{1}) \eqsim P(S_n|S_{n-1}) $$ 这个近似公式表明了一阶马尔科夫性质(markov property): 系统在时间t+1的状态只与系统在时间t的状态有关。
那么,如果我们在严谨一点,将这个关联状态再往前面推一个时间点,得到的就是二阶马尔科夫模型: $$ P(S_n|S_{n-1},S_{n-2},...,S_{1}) \eqsim P(S_n|S_{n-1},S_{n-2}) $$
下面使用马尔科夫假设描述联合概率: $$ P(S_1,S_2,...,S_n) = \prod_{i=1}^n P(S_i,S_{i-1}) $$
总结 : 如果一个随机序列的分布仅由其当前状态确定,则具有markov性质。具有这个性质的随机过程称为马尔科夫随机过程(markov random process)。 对于可观察的状态序列(即状态由数据可知),可以得到一个马尔科夫链模型(markov chain model,MCM),我们可以使用这个模型来做一些预测。 对于不可观察状态,会得到一个隐式马尔科夫模型(hidden markov model,HMM)
接下来我们给出将要用到的马尔科夫链的形式化表示
有限的状态空间(state space) $$ S={S_1,S_2,...S_n} $$
转移概率(transition properties)
函数$f:S \times S \to R$:转化结果为一个N阶方阵,其中N是状态的数量,其中: $0 \le f(a,b) \le 1$:即转移概率的值在0到1之间; $\sum_{b \in S} f(a,b) = 1$:即同一个状态转向当前所有可能的状态的概率和为1;
初始分布(initial distribution)
函数$g:S \times R$,其中: $0 \le g(a) \le 1$ $\sum_{a\in S}g(a) = 1$
马尔科夫链是S中的一个随机过程: 时间0时,这个链的初始状态用分布函数$g$创建; 如果时间t时马尔科夫链的状态为$a$,则时间$t+1$时,对于各个$b \in S$,其状态为b的概率为$f(a,b)$
2、马尔科夫状态表的运用
假设我们已经得到了一张马尔科夫状态表。如下表所示的城市天气变化表:
今天天气\明天天气 晴天(sunny) 有雨(rainy) 多云(cloudy) 有雾(foggy)
晴天(sunny) 有雨(rainy) 多云(cloudy) 有雾(foggy)
0.6 0.5 0.1 0.0
0.1 0.2 0.7 0.3
0.2 0.2 0.1 0.4
0.1 0.1 0.1 0.3
我们假设: 城市天气只包含四种可能,即晴天(sunny)、有雨(rainy)、多云(cloudy)和有雾(foggy); 一天中天气不会变化;
我们来解释这张表的含义,其实我们完全可以以4阶方阵的形式表示,但为了清晰说明,将其以表格展示。
其中每一个数字代表:当前的天气为XX时,明天的天气为XX的概率。例如,第一行第一列的数据0.6,就代表的是当前天气为晴天时,明天天气为晴天的概率为0.6.
我们就可以用马尔科夫性质的思想回答下面的问题:
如果今天的天气状态是晴天,那么明天是多云而且后天有雾的概率是多大?根据马尔科夫链的思想,明天是多余的概率只与今天有关,后天有雾的概率只与明天有关,因此: P = 0.2(第一行第三列数据) * 0.1(第三行第四列) = 0.02
可见,我们的重点在于由数据推导出马尔科夫状态矩阵的过程。
2、分析客户交易数据
假设我们有这样的一些交易数据: 55FRL8G23B,1381907878,2013-01-09,129 9SX0DJG9L4,1381907879,2013-01-09,34 0ANMD0T113,1381907880,2013-01-09,144 W1F4412PA8,1381907881,2013-01-09,26 22Z10EAYC3,1381907882,2013-01-09,167 3R56N17P1H,1381907883,2013-01-09,25 LK0P6K3DE4,1381907884,2013-01-09,25 3A4S4BMPMU,1381907885,2013-01-09,113 OF4CEO2814,1381907886,2013-01-09,138 9ICNYOFS41,1381907887,2013-01-09,79 N4EOB264U6,1381907888,2013-01-09,108 3C0WARCKYJ,1381907889,2013-01-09,204 PTT3BI00AZ,1381907890,2013-01-09,27 14UHHAVQ2Q,1381907891,2013-01-09,73 Z9GFE6TDKF,1381907892,2013-01-09,32 ...
数据意义为(交易ID,顾客ID,交易日期,交易金额)。
2.1、生成状态序列
这一节的目标是将交易序列(transcation sequence)转化为一个状态序列(state sequence)。我们的应用的目的是为了生成以下的输出 $$ customerId(Date_1,Amount_1);(Date_2,Amount_2),...,(Date_n,Amount_n) $$ 其中日期按增序排序。
我们要把这个输出转化为一个状态序列,如下所示: $$ customerId,State_1,State_2,...,State_n $$
我们还需要将(purchase-date,amount)对的有序序列转换为一组马尔科夫链状态。状态由一个代号(两个字母)表示,各个字母的定义如下所示:
上一次交易后经过的时间 与前次交易相比的交易额 S:小 L:显著小于
M:中 L:大
E:基本相同 G:显著大于
因此,我们可以得到9种状态
状态名 上一次交易后的经过时间与其次交易相比的交易额 SL 小:显著小于
SE 小:基本相同
SG 小:显著大于
ML 中:显著小于
ME 中:基本相同
MG 中:显著大于
LL 大:显著小于
LE
LG
大:基本相同
大:显著大于
可以看到,我们的马尔科夫链模型有9个状态(9*9矩阵)。
转换过程可以使用一些小脚本实现,但是如果数据量过大,还是需要一个map过程。
2.2、使用MapReduce生成马尔科夫状态转移矩阵
3、Spark实现
3.1、主类
下面是spark的主任务类。下一章节会列出所使用到的辅助类。 package com.sunrun.movieshow.algorithm.markov; import com.sunrun.movieshow.algorithm.common.SparkHelper; import org.apache.spark.api.java.JavaPairRDD; import org.apache.spark.api.java.JavaRDD; import org.apache.spark.api.java.JavaSparkContext; import scala.Tuple2; import java.io.Serializable; import java.util.*; public class SparkMarkov { public static void main(String[] args) { JavaSparkContext sc = SparkHelper.getSparkContext("markov"); // 1.归约到不同的分区 JavaRDD rdd = sc.textFile("data/markov").coalesce(8); // 2.得到(顾客ID,(交易时间,交易额)) JavaPairRDD> pairRDD = rdd.mapToPair(line -> { // tokens[0] = customer-id // tokens[1] = transaction-id // tokens[2] = purchase-date // tokens[3] = amount String[] tokens = line.split(","); if (tokens.length != 4) { return null; } else { long date = 0; try { date = DateUtil.getDateAsMilliSeconds(tokens[2]); } catch(Exception e) { // 会有异常数据 } int amount = Integer.parseInt(tokens[3]); Tuple2 V = new Tuple2<>(date, amount); return new Tuple2<>(tokens[0], V); } }); /** * (V31E55G4FI,(1356969600000,123)) * (301UNH7I2F,(1356969600000,148)) * (PP2KVIR4LD,(1356969600000,163)) * (AC57MM3WNV,(1356969600000,188)) * ... */ // 4.依据交易ID进行分组 - 用户信息在最后的状态链中是没用的,但他可以限定一些状态切换的内在关系, // 这在很多算法过程中都是隐含条件,需要经验判断。 JavaPairRDD>> customerRDD = pairRDD.groupByKey(); /** * (V31E55G4FI,(1356969600000,123),1356969600000,148)....) * ... */ // 5.创建马尔科夫状态序列 (c_id,<(time1,amount),(time2,amount)>) => (String) JavaPairRDD> stateSequence = customerRDD.mapValues((Iterable> dateAndAmount) -> { List> list = toList(dateAndAmount); Collections.sort(list, TupleComparatorAscending.INSTANCE); // now convert sorted list (be date) into a "state sequence" List stateSequence1 = toStateSequence(list); return stateSequence1; }); /** * stateSequence.saveAsTextFile("out/" + UUID.randomUUID()); * 顾客id,与其相关的状态序列 * (K40E0LA5DL,[LL, MG, SG, SL, SG, MG, SL, SG, SL, SG, LL]) * (ICF0KFGK12,[SG, SL, SE, SG, LL, LG]) * (4N0B1U5HVG,[SG, ML, MG, SG, SL, SG, SL, SG, ML]) * (3KJR1907D9,[SG, SL, ML, SG, ML, LG]) * (47620I9LOD,[LG, SL, ML, MG, SG, SL, SG, SL, SG]) */ // 6.接下来,我们将状态序列以窗口为2的方式依次移动,生成一个个形如((LL, MG),1)的对 JavaPairRDD, Integer> model = stateSequence.flatMapToPair(s -> { // 输出形式((fromState,toState),times) ArrayList, Integer>> mapperOutput = new ArrayList<>(); List states = s._2; if (states == null) { return Collections.emptyIterator(); } else { for (int i = 0; i < states.size() - 1; i++) { String fromState = states.get(i); String toState = states.get(i + 1); Tuple2 k = new Tuple2<>(fromState, toState); mapperOutput.add(new Tuple2<>(k, 1)); } } return mapperOutput.iterator(); }); /** * model.saveAsTextFile("out/model"); * ((LG,LL),1) * ((LL,MG),1) * ((MG,SG),1) * ((SG,SL),1) * ((SL,ME),1) * ((ME,MG),1) * */ // 7.我们需要将这些结果组合归约,将相同的状态序列进行合并,即从(f,t),1) => ((f,t),3000)的形式。 JavaPairRDD, Integer> markovModel = model.reduceByKey((a, b) -> a + b); /** * markovModel.saveAsTextFile("/out/markov"); * ((LL,SL),993) * ((MG,LL),1859) * ((LE,ME),25) * ((SL,ME),1490) * ((LG,ME),153) * ((ML,LG),3991) * ((ME,ME),58) */ // 8.我们格式化一下输出,将其形式转变为(f,t,times)的形式 JavaRDD markovFormatModel = markovModel.map(t -> t._1._1 + "\t" + t._1._2 + "\t" + t._2); // 9.将结果存储到HDFS服务器,当然也可以存储到本地,这时候解析类就要使用本地文件系统的API String markovFormatModelStorePath = "hdfs://10.21.1.24:9000/markov/"; markovFormatModel.saveAsTextFile(markovFormatModelStorePath); // 9.将最终结果进行转换,生成马尔科夫概率模型 MarkovTableBuilder.transport(markovFormatModelStorePath); /** 这是一个state阶的方阵,A(ij)表示状态i到状态j的转化概率 * 0.03318,0.02441,0.6608,0.1373,0.007937,0.02398,0.06456,0.009522,0.03832 * 0.3842,0.02532,0.2709,0.1260,0.009590,0.01331,0.1251,0.01083,0.03477 * 0.6403,0.02881,0.05017,0.1487,0.01338,0.008602,0.08359,0.01446,0.01196 * 0.02081,0.002368,0.7035,0.01170,0.004638,0.1518,0.03901,0.005933,0.06030 * 0.4309,0.02140,0.2657,0.1277,0.009697,0.02006,0.08159,0.009530,0.03344 * 0.1847,0.01816,0.5316,0.1303,0.007175,0.02351,0.06265,0.008136,0.03379 * 0.01847,0.004597,0.6115,0.02068,0.003091,0.1346,0.06828,0.01424,0.1245 * 0.2250,0.01900,0.2427,0.06291,0.006335,0.03182,0.2757,0.03801,0.09847 * 0.2819,0.01944,0.1954,0.07990,0.008015,0.03202,0.2612,0.04427,0.07781 */ } // 将迭代器转化为数组 static List> toList(Iterable> iterable) { List> list = new ArrayList>(); for (Tuple2 element: iterable) { list.add(element); } return list; } // 按时间进行排序 static class TupleComparatorAscending implements Comparator>, Serializable { final static TupleComparatorAscending INSTANCE = new TupleComparatorAscending(); @Override public int compare(Tuple2 t1, Tuple2 t2) { // return -t1._1.compareTo(t2._1); // sorts RDD elements descending return t1._1.compareTo(t2._1); // sorts RDD elements ascending } } // 将一个有序的交易序列(List>)转化为状态序列(List),其中各个元素分别表示一个马尔科夫状态。 static List toStateSequence(List> list){ // 没有足够的数据 if(list.size() < 2){ return null; } List stateSequence = new ArrayList<>(); // == 两两配对计算结果 Tuple2 prior = list.get(0); for (int i = 1; i < list.size(); i++) { Tuple2 current = list.get(i); // === 计算时间差(天),由于数据是以ms计数的,因此需要转化为天(1d = 24*60*60*1000=86400000ms) long dayDiff = (current._1 - prior._1) / 86400000; // === 获取交易额信息 int priorAmount = prior._2; int currentAmount = current._2; // === 根据业务规则转化为字母表示 // ==== 处理时间关系 String dd = null; if(dayDiff < 30){ dd = "S"; }else if(dayDiff < 60){ dd = "M"; }else { dd = "L"; } // ==== 处理金额关系: 使用两次交易额的比重 String ad = null; if(priorAmount < 0.9 * currentAmount){ ad = "L"; }else if(priorAmount < 1.1 * currentAmount){ ad = "E"; }else{ ad = "G"; } // === 组合结果 String element = dd + ad; stateSequence.add(element); // 大小为2的窗口前进一格 prior = current; } return stateSequence; } }
3.2、辅助类
日期处理类 package com.sunrun.movieshow.algorithm.markov; import java.text.SimpleDateFormat; import java.util.Date; public class DateUtil { static final String DATE_FORMAT = "yyyy-MM-dd"; static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat(DATE_FORMAT); /** * Returns the Date from a given dateAsString */ public static Date getDate(String dateAsString) { try { return SIMPLE_DATE_FORMAT.parse(dateAsString); } catch(Exception e) { return null; } } /** * Returns the number of milliseconds since January 1, 1970, * 00:00:00 GMT represented by this Date object. */ public static long getDateAsMilliSeconds(Date date) throws Exception { return date.getTime(); } /** * Returns the number of milliseconds since January 1, 1970, * 00:00:00 GMT represented by this Date object. */ public static long getDateAsMilliSeconds(String dateAsString) throws Exception { Date date = getDate(dateAsString); return date.getTime(); } public static String getDateAsString(long timestamp) { return SIMPLE_DATE_FORMAT.format(timestamp); } }
2、输入输出工具类 package com.sunrun.movieshow.algorithm.markov; import java.io.InputStream; import java.io.OutputStream; import java.io.BufferedReader; // import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.util.LineReader; /** * This class provides convenient methods for accessing * some Input/Output methods. * * @author Mahmoud Parsian (mahmoud.parsian@yahoo.com) * */ public class InputOutputUtil { public static void close(LineReader reader) { if (reader == null) { return; } // try { reader.close(); } catch (Exception ignore) { } } public static void close(OutputStream stream) { if (stream == null) { return; } // try { stream.close(); } catch (Exception ignore) { } } public static void close(InputStream stream) { if (stream == null) { return; } // try { stream.close(); } catch (Exception ignore) { } } public static void close(FSDataInputStream stream) { if (stream == null) { return; } // try { stream.close(); } catch (Exception ignore) { } } public static void close(BufferedReader reader) { if (reader == null) { return; } // try { reader.close(); } catch (Exception ignore) { } } }
3、马尔科夫状态处理类 package com.sunrun.movieshow.algorithm.markov; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 输入数据生成马尔科夫状态表 */ public class MarkovTableBuilder { // 状态的数量 private int numberOfState; private int scale; // 状态表 private double[][] table = null; // 状态序列 private Map states = null; public MarkovTableBuilder(int numberOfState, int scale){ this(numberOfState); this.scale = scale; } private MarkovTableBuilder(int numberOfState){ this.numberOfState = numberOfState; table = new double[numberOfState][numberOfState]; initStates(); } // 初始化state状态 private void initStates(){ states = new HashMap(); states.put("SL", 0); states.put("SE", 1); states.put("SG", 2); states.put("ML", 3); states.put("ME", 4); states.put("MG", 5); states.put("LL", 6); states.put("LE", 7); states.put("LG", 8); } // 将状态信息添加到状态表 public void add(StateItem item){ // 获取该状态对应的角标 int row = states.get(item.fromState); int column = states.get(item.toState); table[row][column] = item.count; } public void normalize() { // // 拉普拉斯校正:一般通过将所有的计数+1来进行。see: http://cs.nyu.edu/faculty/davise/ai/bayesText.html for (int r = 0; r < numberOfState; r++) { boolean gotZeroCount = false; for (int c = 0; c < numberOfState; c++) { if(table[r][c] == 0) { gotZeroCount = true; break; } } if (gotZeroCount) { for (int c = 0; c < numberOfState; c++) { table[r][c] += 1; } } } // normalize for (int r = 0; r < numberOfState; r++) { double rowSum = getRowSum(r); for (int c = 0; c < numberOfState; c++) { table[r][c] = table[r][c] / rowSum; } } } // 获取rowNumber行的累加结果 public double getRowSum(int rowNumber) { double sum = 0.0; for (int column = 0; column < numberOfState; column++) { sum += table[rowNumber][column]; } return sum; } /** * 存储状态表:作为示例,只是将结果输出即可。 */ private void persist() { for (int row = 0; row < numberOfState; row++) { StringBuilder builder = new StringBuilder(); for (int column = 0; column < numberOfState; column++) { double element = table[row][column]; builder.append(String.format("%.4g", element)); if (column < (numberOfState - 1)) { builder.append(","); } } System.out.println(builder.toString()); } } public static void transport(String markovFormatDataPath){ List items = ReadDataFromHDFS.readDirectory(markovFormatDataPath); MarkovTableBuilder markovTableBuilder = new MarkovTableBuilder(9); for (StateItem item : items) { markovTableBuilder.add(item); } // 归一化数据 markovTableBuilder.normalize(); // 存储马尔科夫状态表 markovTableBuilder.persist(); } }
4、从文件系统读取数据的处理类 package com.sunrun.movieshow.algorithm.markov; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.log4j.Logger; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; /** * Class containing a number of utility methods for manipulating * Hadoop's SequenceFiles. * * * @author Mahmoud Parsian * */ public class ReadDataFromHDFS { private ReadDataFromHDFS() { } public static List readDirectory(String path) { return ReadDataFromHDFS.readDirectory(new Path(path)); } public static List readDirectory(Path path) { FileSystem fs; try { fs = path.getFileSystem(new Configuration()); } catch (IOException e) { System.out.println("Unable to access the hadoop file system!"); throw new RuntimeException("Unable to access the hadoop file system!"); } List list = new ArrayList(); try { FileStatus[] stat = fs.listStatus(path); for (int i = 0; i < stat.length; ++i) { if (stat[i].getPath().getName().startsWith("part")) { List pairs = readFile(stat[i].getPath(), fs); list.addAll(pairs); } } } catch (IOException e) { System.out.println("Unable to access the hadoop file system!"); throw new RuntimeException("Error reading the hadoop file system!"); } return list; } @SuppressWarnings("unchecked") public static List readFile(Path path, FileSystem fs) { List list = new ArrayList(); FSDataInputStream stream = null; BufferedReader reader = null; try { stream = fs.open(path); reader = new BufferedReader(new InputStreamReader(stream)); String line; while ((line = reader.readLine()) != null) { // line = <,> String[] tokens = line.split("\t"); // TAB separator if (tokens.length == 3) { StateItem item = new StateItem(tokens[0], tokens[1], Integer.parseInt(tokens[2])); list.add(item); } } } catch (IOException e) { System.out.println("readFileIntoCoxRegressionItem() failed!"); throw new RuntimeException("readFileIntoCoxRegressionItem() failed!"); } finally { InputOutputUtil.close(reader); InputOutputUtil.close(stream); } return list; } public static void main(String[] args) throws Exception { String path = "hdfs://10.21.1.24:9000/markov/"; List list = readDirectory(path); System.out.println("list="+list.toString()); } }
5、马尔科夫状态实体类 package com.sunrun.movieshow.algorithm.markov; /** * TableItem represents an item of a Markov State Transition Model * as a Tuple3 * */ public class StateItem { String fromState; String toState; int count; public StateItem(String fromState, String toState, int count) { this.fromState = fromState; this.toState = toState; this.count = count; } /** * for debugging ONLY */ public String toString() { return "{"+fromState+"," +toState+","+count+"}"; } }
4、使用最终的马尔科夫表进行预测
前面我已经在代码注释中拿出了最后的分析结果:
SL SE SG ML ME MG LL LE LG
SL SE SG ML ME MG LL LE LG
0.03318 0.3842 0.6403 0.02081 0.4309 0.1847 0.01847 0.2250 0.2819
0.02441 0.02532 0.02881 0.002368 0.02140 0.01816 0.004597 0.01900 0.01944
0.6608 0.2709 0.05017 0.7035 0.2657 0.5316 0.6115 0.2427 0.1954
0.1373 0.1260 0.1487 0.01170 0.1277 0.1303 0.02068 0.06291 0.07990
0.007937 0.009590 0.01338 0.004638 0.009697 0.007175 0.003091 0.006335 0.008015
0.02398 0.01331 0.008602 0.1518 0.02006 0.02351 0.1346 0.03182 0.03202
0.06456 0.1251 0.08359 0.03901 0.08159 0.06265 0.06828 0.2757 0.2612
0.009522 0.01083 0.01446 0.005933 0.009530 0.008136 0.01424 0.03801 0.04427
0.03832 0.03477 0.01196 0.06030 0.03344 0.03379 0.1245 0.09847 0.07781
参考
数据算法 —— Mahmoud Parsian(很喜欢该作者写的这本书,非常详细)
附录
1、ruby脚本
mark_plan.rb #!/usr/bin/ruby require '../lib/util.rb' require 'Date' xaction_file = ARGV[0] model_file = ARGV[1] userXactions = {} model = [] states = ["SL", "SE", "SG", "ML", "ME", "MG", "LL", "LE", "LG"] # read all xactions File.open(xaction_file, "r").each_line do |line| items = line.split(",") custID = items[0] if (userXactions.key? custID) hist = userXactions[custID] else hist = [] userXactions[custID] = hist end hist << items[2, items.size - 2] end #read model File.open(model_file, "r").each_line do |line| items = line.split(",") #puts "#{line}" row = [] items.each do |item| row << item.to_i #puts "#{item}" end model << row #puts "#{row}" end # marketing time userXactions.each do |cid, xactions| seq = [] last_date = Date.parse "2000-01-01" xactions.each_with_index do |xaction, index| if (index > 0) prevXaction = xactions[index-1] prDate = Date.parse prevXaction[0] prAmt = prevXaction[1].to_i date = Date.parse xaction[0] last_date = date amt = xaction[1].to_i daysDiff = date - prDate amtDiff = amt - prAmt if (daysDiff < 30) dd = "S" elsif (daysDiff < 60) dd = "M" else dd = "L" end if (prAmt < 0.9 * amt) ad = "L" elsif (prAmt < 1.1 * amt) ad = "E" else ad = "G" end seq << (dd + ad) end end if (!seq.empty?) last = seq[-1] row_index = states.index(last) row = model[row_index] max_col = row.max col_index = row.index(max_col) next_state = states[col_index] if (next_state.start_with?("S")) next_date = last_date + 15 elsif (next_state.start_with?("M")) next_date = last_date + 45 else next_date = last_date + 90 end #puts "#{cid}, #{last}, #{row_index}, #{max_col}, #{col_index}, #{next_state}, #{last_date}, #{next_date}" puts "#{cid}, #{next_date}" end end
buy_xaction.rb #!/usr/bin/ruby require '../lib/util.rb' require 'Date' custCount = ARGV[0].to_i daysCount = ARGV[1].to_i visitorPercent = ARGV[2].to_f custIDs = [] xactionHist = {} # transition probability matrix idGen = IdGenerator.new 1.upto custCount do custIDs << idGen.generate(10) end xid = Time.now().to_i date = Date.parse "2013-01-01" 1.upto daysCount do numXaction = visitorPercent * custCount factor = 85 + rand(30) numXaction = (numXaction * factor) / 100 1.upto numXaction do custID = custIDs[rand(custIDs.size)] if (xactionHist.key? custID) hist = xactionHist[custID] lastXaction = hist[-1] lastDate = lastXaction[0] lastAmt = lastXaction[1] numDays = date - lastDate if (numDays < 30) amount = lastAmt < 40 ? 50 + rand(20) - 10 : 30 + rand(10) - 5 elsif (numDays < 60) amount = lastAmt < 80 ? 100 + rand(40) - 20 : 60 + rand(20) - 10 else amount = lastAmt < 150 ? 180 + rand(60) - 30 : 120 + rand(40) - 20 end else hist = [] xactionHist[custID] = hist amount = 40 + rand(180) end xaction = [] xaction << date xaction << amount hist << xaction xid = xid + 1 puts "#{custID},#{xid},#{date},#{amount}" end date = date.next end
人工智能
2019-03-20 17:18:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
前几天的3.15晚会上曝光了利用智能机器人,一天打4万个骚扰电话,从而赚取利润的黑色产业链。
阿里的工程师恼了,技术是用来让人们生活变美好的,不是被利用来走向阴暗的。
机器人的问题交给机器人!
工程师们用业余时间开发的AI机器人——“二哈”要登场了~
视频感受一下咱们“二哈”,连女推销员都丝毫没有察觉。
1、 别惹程序员,用机器人对付机器人
研发“二哈”,其实就是阿里的技术人,对日益普遍的骚扰电话很头疼,而且更可气的是,大量骚扰电话是机器自动拨出的,成本越来越低。
这些骚扰电话,甚至还影响到日常工作,会议开着开着,经常被各类电话打断导致会议终中断。于是阿里AI实验室的同学们开始思考着如何用技术的方式解决问题。
阿里AI实验室天猫精灵算法团队,聚集着语音识别、NLP、知识图谱……全链条的技术人才,当技术人聚在一起,那就能搞事情了。
于是他们先以“课余”项目开始,参与的同学都很开心。一方面是解气,另一方面更清楚背后带来的意义。
没想到在今年3.15晚会上,机器人骚扰电话引起如此大关注。
于是团队决定公开最新研发成果,“二哈”也正式从幕后走到台前,一炮而红。
2、 我们要做到真假难辨
“二哈”是这个智能防骚扰电话技术的项目代号。当用户在手机上开通了这项服务,在接到骚扰来电时,用户可以直接转接给机器人接听。
我们都知道哈士奇之所以被喊作“二哈”,就是它欢乐多,工作起来又相当认真。阿里的程序员们,就是希望这个“课余”爱好的项目,给自己带来快乐,也能帮主人扫除骚扰电话的焦虑。
而“二哈”背后,其实主要使用了智能聊天技术。
所谓“智能聊天”,就是要理解用户请求,同时用强大的知识图谱制作聊天的知识点,通过跟用户对话,把知识图谱里的知识灌输给用户,同时也引导用户反馈。
听起来,简单的一段话,要真正实现聊天聊得“真假难辨”却十分不容易。
于是,我们特地请教了阿里达摩院AI实验室语音助手首席科学家聂再清。
他告诉大家,要做到真假难辨,最核心的是以下3点:
第一,接住用户的每一句话。
因为用户的输入空间非常大,要理解和聪明的回复来电者的每一句话很有难度。
对于一些不是“二哈”知识领域的问题,阿里AI目前采用了闲聊(ChitChat)的技术,从互联网上公开的人类对话库中来找到最适合回复。目标是让来电者看不出“二哈”可能的知识缺乏。
第二,主动提出一个相关问题。
这更多是一个对话策略学习的工作,需要让来电者知道“二哈”真能理解他们的话,并提出只有理解了对话上下文,才能提出的好问题。
一味被动接话,很容易被识破。
该项挑战非常大,核心就是一套聊天机器人对话策略学习框架,让“二哈”这样的聊天机器人在不同的场景下都可以持续学习。
通过和人类不断对话,“二哈”AI会通过深度强化学习越来越好地知道如何提问才能更好地达成他的目标。
最后,像真人一样的语音语调以及停顿。
如果推销广告的骚扰电话,通过声音判断初接电话的是个机器人,他们就不会继续聊下去了。
所以“二哈”在语音合成方面做了很多工作。
阿里AI最新算法利用Tacotron加上基于神经网络的声码器算法,合成出极其逼真的人声,但还有很大比例情况不能通过图灵测试。于是“二哈”现在采取了过渡性方案,把非常高频的回复借用真人录播。
感受一下“二哈”真声和“二哈”的互相调戏学习,竟然没有一点违和感呢。
3、 不止用来对付骚扰电话
“二哈”就只是帮对付骚扰电话而已嘛?
当然不是咯。
项目组的工程师说,“二哈”的进一步的目标是成为每个人的AI电话秘书,除了帮主人应付骚扰电话,还可以在主人繁忙的时候询问来电的主要意图,也能帮主人预约议程。
在你不方便接电话时帮接听来电,并转换成文字向你“汇报”。
“二哈”这样的AI电话秘书,可以利用个性化TTS,模仿出跟主人声音极尽逼真的声音。可以把它看作是你的‘声替’,也可以用任何喜欢的声音替你接打电话。
阿里工程师还在畅想,是否有一天,它还还可以帮助聋哑人打电话?技术的进步可以延伸人的能力,也可以弥补人的缺陷。
阿里人常说,所有的异想天开,终究化为寻常。希望这样的“寻常”能早点到来!
讲真,这样的私人秘书,你期不期待?
最后告诉你一个小技能:在支付宝搜索天猫精灵,或直接打开天猫精灵App,就可以调戏这只二哈!
原文链接
人工智能
2019-03-20 11:32:00
「深度学习福利」大神带你进阶工程师,立即查看>>>

新发布1.7.0版本的hanlp自然语言处理工具包差不多已经有半年时间了,最近也是一直在整理这个新版本hanlp分词工具的相关内容。不过按照当前的整理进度,还需要一段时间再给大家详细分享整理的内容。昨天正好看到的这篇关于关于1.7.0版本hanlp分词在spark中的使用介绍的文章,顺便分享给大家一起学习一下!
以下为分享的文章内容:
HanLP分词,如README中所说,如果没有特殊需求,可以通过maven配置,如果要添加自定义词典,需要下载“依赖jar包和用户字典".
直接"java xf hanlp-1.6.8-sources.jar" 解压源码,把源码加入工程(依赖本地jar包,有些麻烦,有时候到服务器有找不到jar包的情况)
按照文档操作,在Spark中分词,默认找的是本地目录,所以如果是在driver中分词是没有问题的。但是如果要分布式分词,是要把词典目录放在HDFS上面,因为这样每台机器才可以访问到 【参考代码】
最好把新增词典放在首位,第一次使用时,HanLP会把新增txt文件,生成bin文件,这个过程比较慢。但是只需要跑一次,它会把bin文件写到HDFS路径上面,第二次以后速度就快一些了。
注意到issue中说,只可以在mapPartition中使用。

参考scala代码

class HadoopFileIoAdapter extends IIOAdapter {

override def create(path: String): java.io.OutputStream = {
val conf: Configuration = new Configuration()
val fs: FileSystem = FileSystem.get(URI.create(path), conf)
fs.create(new Path(path))
}

override def open(path: String): java.io.InputStream = {
val conf: Configuration = new Configuration()
val fs: FileSystem = FileSystem.get(URI.create(path), conf)
fs.open(new Path(path))
}
}

def myfuncPerPartition_ ( iter : Iterator [String] ) : Iterator[(Int, mutable.Buffer[String])] = {
println("run in partition")
val keyWordNum = 6
HanLP.Config.IOAdapter = new HadoopFileIoAdapter
val ret = iter.filter(_.split(",",2).length==2)
.map(line=>(line.split(",",2)(1).trim.hashCode, HanLP.extractKeyword(line.split(",",2)(0),keyWordNum)
.map(str=>str.filterNot(stopChar.contains(_))).filter(w=>(w.length>1 || ( w.length==1 && white_single_word.contains(w(0))) ))
.filterNot(stopWords.contains(_)).take(keyWordNum).distinct))
ret
}

//调用
raw_data.repartition(100).mapPartitions(myfuncPerPartition_)
---------------------

人工智能
2019-03-11 11:56:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
前言 只有光头才能变强。 文本已收录至我的GitHub仓库,欢迎Star: https://github.com/ZhongFuCheng3y/3y
最近在学习TensorFlow的相关知识,了解了TensorFlow一些基础的知识,现在周末有空了,就写写一些笔记,记录一下自己的成长~
总的来说,TensorFlow还是一个比较新的技术,有兴趣的同学不妨跟着我的笔记,一起学学呗(反正没坏处)~
前面回顾: 外行人都能看得懂的机器学习,错过了血亏! 这是我看过最好的「机器学习」科普文章了 神经网络浅讲:从神经元到深度学习 知识背景:没有Python基础,没有机器学习基础,可以说是真正从零学TensorFlow的了。
一、安装Tensorflow所需要的环境
1.1安装Python环境 使用环境: Mac
Python有好多个版本,在Mac中自带的Python版本是 2.7 ,但相对而言比较老了。现在一般用 Python3.x 了,本次下载的版本是 3.5.6
我安装Python所使用方法的大致步骤: 安装Homebrew 安装pyenv 在 .bash_profile 添加环境变量 让环境变量生效 安装 3.X版本python
详情可参考如下的链接(总的来说,我根据下面的教程一下子就安装了我想要的Python版本,还是非常不错的。): Mac下安装多版本python: https://www.cnblogs.com/webgiser/p/7463974.html pyenv相关的命令(常用的pyenv命令): https://www.jianshu.com/p/af1f8d7b6b31
在安装Python的时候也发现了一个小知识点: Mac一般使用bash作为默认的shell,会有好几个环境变量,其中 etc/profile 是 系统级 的,还有几个 用户级别 的环境变量,比如说: ~/.bash_profile 如果修改的是系统级别的环境变量,也就是 etc/profile ,在保存的时候只能是 :wq !覆盖,不然会出现readonly错误
(至于TensorFlow和numpy依赖的下载,这里我就不说了,就两条命令就搞掂啦)
1.2PyCharm编辑器
Java有 IDEA 神器,同样的,Python也有 PyCharm ,同样是JetBrains出产的。 我在之前从来没使用过PyCharm,也没写过一句的Python代码。
把Pycharm安装好了之后,我想当然就 new project 去用了,然后就 next,next,next ,当成IDEA来用。但发现了一个问题:我在之前 明明装好了 TensorFlow和numpy的依赖,在PyCharm环境下却 识别不出来 !在 命令行 窗口下,依赖是存在的!
后来才发现:如果用PyCharm去new一个project,会 默认建一个解析器 在当前的项目目录下。而PyCharm会遵守“就近原则”使用当前项目路径下的解析器。而我们添加的依赖(TensorFlow、numpy)是在我们安装Python的路径下的,这就导致了在命令行下找到依赖,而在PyCharm中找不到依赖。
解决也很简单:在PyCharm 指定 一下我们安装Python的路径,切换一下就好了。
参考资料: 关于pip安装第三方库,但pycharm中却无法识别的问题;以及pycharm安装第三方库的方法解析 https://blog.csdn.net/weixin_41287260/article/details/83957731
二、体验TensorFlow
好的,我们现在已经安装好TensorFlow所需要的环境了!(看起来好简单,但还是花了我不少时间....)
官网的Demo链接(需要科学上网): https://www.tensorflow.org/tutorials/keras/basic_classification
首先我们来看一下这个例子可以干些什么:我们有非常多张的图片( 数据集 ),这些图片有不同的类型(比如衣服、鞋子、裤子, 一共有10种类型 ),把这些数据集扔进我们的神经网络里头,生成出 模型 。有了模型以后,当我们再将类似的图片扔进去,这个模型可以帮我们 预测 这张图片是衣服还是鞋子还是裤子。
随后,我跟着官网的代码跑了一(代码我都只是一步一步 复制粘贴 ),最后跑起来: # TensorFlow and tf.keras import tensorflow as tf from tensorflow import keras # Helper libraries import numpy as np print(tf.__version__) # 加载数据、区分出测试数据和训练数据 # 注意:如果已经下过,重复下载的话,可能会出现EOFError: Compressed file ended before the end-of-stream marker was reached错误 fashion_mnist = keras.datasets.fashion_mnist (train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data() # 分类的列表 class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot'] # 查看数据的值 print(train_images.shape) # 样本的shape(可以看出有多少条样本、维度) print(len(train_labels)) # label的个数,有多少个样本,就应该有多少个label print(train_labels) # label的值,对应上面分类列表(从0到9) # 对测试数据和训练数据进行预处理(实际上就是归一化) train_images = train_images / 255.0 test_images = test_images / 255.0 # 设置层 (初始处理)--- 建立神经层 model = keras.Sequential([ keras.layers.Flatten(input_shape=(28, 28)), keras.layers.Dense(128, activation=tf.nn.relu), keras.layers.Dense(10, activation=tf.nn.softmax) ]) # 损失函数、优化器、指标 model.compile(optimizer=tf.train.AdamOptimizer(), loss='sparse_categorical_crossentropy', metrics=['accuracy']) # 将训练集丢进去,训练出模型(Model) model.fit(train_images, train_labels, epochs=5) # 将测试数据丢到模型中,评估一下得分(准确率) test_loss, test_acc = model.evaluate(test_images, test_labels) print('Test accuracy:', test_acc) # 评估完准确率以后,我们可以对测试数据进行预测 predictions = model.predict(test_images) # 选第一个样本预测后的得出最有可能结果 print(np.argmax(predictions[0])) # 对比结果 print(test_labels[0])
跑出来的结果:
(后期注释:这是TensorFlow的版本)
1.12.0
(后期注释:这是TensorFlow下载数据集的日志) Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz 32768/29515 [=================================] - 0s 3us/step Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz 26427392/26421880 [==============================] - 12s 0us/step Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz 8192/5148 [===============================================] - 0s 0us/step Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz 4423680/4422102 [==============================] - 2s 0us/step
(后期注释:样本的shape)
(60000, 28, 28)
(后期注释:样本有多少条,对应的label就有多少条)
60000
(后期注释:label的值是从0-9,表示有九种类别)
[9 0 0 ... 3 0 5]
(后期注释:开始训练) Epoch 1/5 2019-02-19 14:00:46.842852: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA 60000/60000 [==============================] - 4s 65us/step - loss: 0.4995 - acc: 0.8246 Epoch 2/5 60000/60000 [==============================] - 4s 62us/step - loss: 0.3734 - acc: 0.8655 Epoch 3/5 60000/60000 [==============================] - 4s 63us/step - loss: 0.3346 - acc: 0.8788 Epoch 4/5 60000/60000 [==============================] - 4s 63us/step - loss: 0.3102 - acc: 0.8861 Epoch 5/5 60000/60000 [==============================] - 4s 63us/step - loss: 0.2918 - acc: 0.8916 10000/10000 [==============================] - 0s 36us/step
(后期注释:预测出来的精确度)
Test accuracy: 0.8514
(后期注释:选第一个样本进行预测,并对比实际的结果) 9 9
参考资料: TensorFlow官网的例子(需要科学上网才能进..) Tensorflow学习笔记之一:训练你的第一个神经网络——基础分类 https://www.jianshu.com/p/d4fb3a391d22
2.1总结一下使用TensorFlow的步骤 加载 数据:使用dataset的api加载数据,并将数据集 分成 训练数据和测试数据 检查 数据:检查 dataSet 的数据有没有问题(例如,样本的记录数、label的记录数等) 对数据 预处理 :对测试数据和训练数据进行 归一化 处理,目的:减少因为数值的大小所带来的影响( 一般我们会将值都缩小在一个小的范围内 ) 建立神经网络 :(输入层、隐藏层、输出层) 为模型定义损失函数、优化器、指标 将训练数据丢进我们的神经网络中,生成出Model 将测试数据丢进我们生成好的Model进行 评估 ,预测出我们的准确率
三、TensorFlow介绍
3.1什么是TensorFlow
如果去Google搜关键字“TensorFlow”,那可能你会看到这么一句话: An open source machine learning framework for everyone.
没错,TensorFlow就是一个机器学习的 框架 。至于框架,相信大家也比较好理解了;类比到Java,比如说我们的Spring框架给我们封装了好多好用的API,简化我们的开发(想想当年写Servlet的时候!)
TensorFlow作为机器学习的框架,同样也给我们封装了好多好用的API,能够 降低 学习机器学习的 门槛 。 就拿上面的例子来说,没想到 那么少的代码 就可以跑机器学习的“HelloWorld”了!
至于机器学习和神经网络的相关基础,我 强烈 建议读读这两篇文章!通俗易懂的 科普 文章: 这是我看过最好的「机器学习」科普文章了 神经网络浅讲:从神经元到深度学习
3.2TensorFlow的架构
我们可以发现上面的Demo所用的基础语言是Python,但不要认为TensorFlow就是Python的一个框架。我看到过一个比喻,觉得写得挺好的,粘贴一下: Python 和 Tensorflow 之间的联系,可以类比 Javascript 和 HTML 之间的关系。Javascript 是一种全功能的编程语言,可以实现各种出色的效果。HTML 是用于表示某种类型的实用计算抽象(这里指的是可由 Web 浏览器呈现的内容)的框架。Javascript 在交互式网页中的作用是 组装浏览器看到的 HTML 对象 ,然后在需要时通过将其更新为新的 HTML 来与其交互。 作者:AI前线 链接: https://juejin.im/post/5b345a49f265da599c561b25
下面再来看看TensorFlow的架构图(Python 只是 对TensorFlow进行了封装)
TensorFlow的引擎也是分了很多模块的(这里我们简单了解一下):
最后
总结一下这篇文章: 安装TensorFlow必要的环境 跟着官方文档, 体验 一下TensorFlow(机器学习)的“HelloWorld” 根据给出的例子, 猜出 使用TensorFlow(机器学习)时需要做哪些步骤 TensorFlow就是一个机器学习(深度学习)的框架,提供了很多 实用 的API方便我们去玩机器学习(深度学习)。
相信看到这里,很多人都跟我之前一样, 一脸懵逼 。对官方给出的例子中的API不熟悉,去查阅相关资料的时候又发现有好多机器学习相关的 术语 ,对这些术语又不了解。然后就循环懵逼.. while(true){ // 循环懵逼.. }
其实回想 刚学Java的时候 ,也是这么一个过程,当你从屏幕看到“HelloWorld”了以后, 大概率 来说也是不了解相关的API具体做了什么事(甚至连API都不知道是啥意思)。但花一段时间去学习了以后,就会发现,原来HelloWorld是真的简单! public static void main(String[] args) { System.out.println("Hello World"); }
后续我会继续更新我学习TensorFlow时的一些 笔记 ,有兴趣的小伙伴不妨跟着我一起学习~
另外,从文章的开头我也已经说了,我对Python、机器学习都是没有相关基础的,如果有写错的地方不妨在评论区留言指正。
下一篇预告:TensorFlow是什么意思?Tensor?Flow?介绍TensorFlow一些最基础的知识以及常见的机器学习术语。 乐于输出 干货 的Java技术公众号:Java3y。公众号内有200多篇 原创 技术文章、海量视频资源、精美脑图,不妨来 关注 一下!
觉得我的文章写得不错,不妨点一下 赞 !
人工智能
2019-03-09 14:21:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
《深度学习引擎-PyTorch资源集锦》包含大量与 PyTorch ( https://pytorch.org/ )相关的资源链接,带你快速玩转基于神经网络的深度学习,进入人工智能的神秘领地。链接包括:入门教程,应用实例,图像、视觉、CNN相关实现,对抗生成网络、生成模型、GAN实现,机器翻译、问答系统、NLP实现,先进视觉推理系统,深度强化学习实现,通用神经网络高级应用等等。
入门系列教程 PyTorch Tutorials
https://github.com/MorvanZhou/PyTorch-Tutorial.git
著名的“莫烦”PyTorch系列教程的源码。 Deep Learning with PyTorch: a 60-minute blitz
http://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html
PyTorch官网推荐的由网友提供的60分钟教程,本系列教程的重点在于介绍PyTorch的基本原理,包括自动求导,神经网络,以及误差优化API。 Simple examples to introduce PyTorch
https://github.com/jcjohnson/pytorch-examples.git
由网友提供的PyTorch教程,通过一些实例的方式,讲解PyTorch的基本原理。内容涉及Numpy、自动求导、参数优化、权重共享等。 PyTorch支持Kubernetes集群, https://my.oschina.net/u/2306127/blog/1817835 Kubeflow 使用指南, https://my.oschina.net/u/2306127/blog/1808582 pytorch-operator 项目源码, https://github.com/kubeflow/pytorch-operator pytorch-operator on Kubernetes, https://my.oschina.net/u/2306127/blog/1811457
入门实例 Ten minutes pyTorch Tutorial
https://github.com/SherlockLiao/pytorch-beginner.git
知乎上“十分钟学习PyTorch“系列教程的源码。 Official PyTorch Examples
https://github.com/pytorch/examples
官方提供的实例源码,包括以下内容:
MNIST Convnets
Word level Language Modeling using LSTM RNNs
Training Imagenet Classifiers with Residual Networks
Generative Adversarial Networks (DCGAN)
Variational Auto-Encoders
Superresolution using an efficient sub-pixel convolutional neural network
Hogwild training of shared ConvNets across multiple processes on MNIST
Training a CartPole to balance in OpenAI Gym with actor-critic
Natural Language Inference (SNLI) with GloVe vectors, LSTMs, and torchtext
Time sequence prediction - create an LSTM to learn Sine waves PyTorch Tutorial for Deep Learning Researchers
https://github.com/yunjey/pytorch-tutorial.git
据说是提供给深度学习科研者们的PyTorch教程←_←。教程中的每个实例的代码都控制在30行左右,简单易懂,内容如下:
PyTorch Basics
Linear Regression
Logistic Regression
Feedforward Neural Network
Convolutional Neural Network
Deep Residual Network
Recurrent Neural Network
Bidirectional Recurrent Neural Network
Language Model (RNN-LM)
Generative Adversarial Network
Image Captioning (CNN-RNN)
Deep Convolutional GAN (DCGAN)
Variational Auto-Encoder
Neural Style Transfer
TensorBoard in PyTorch PyTorch-playground
https://github.com/aaron-xichen/pytorch-playground.git
PyTorch初学者的Playground,在这里针对一下常用的数据集,已经写好了一些模型,所以大家可以直接拿过来玩玩看,目前支持以下数据集的模型。
mnist, svhn
cifar10, cifar100
stl10
alexnet
vgg16, vgg16_bn, vgg19, vgg19_bn
resnet18, resnet34, resnet50, resnet101, resnet152
squeezenet_v0, squeezenet_v1
inception_v3
图像、视觉、CNN相关实现 PyTorch-FCN
https://github.com/wkentaro/pytorch-fcn.git
FCN(Fully Convolutional Networks implemented) 的PyTorch实现。 Attention Transfer
https://github.com/szagoruyko/attention-transfer.git
论文 “Paying More Attention to Attention: Improving the Performance of Convolutional Neural Networks via Attention Transfer” 的PyTorch实现。 Wide ResNet model in PyTorch
https://github.com/szagoruyko/functional-zoo.git
一个PyTorch实现的 ImageNet Classification 。 CRNN for image-based sequence recognition
https://github.com/bgshih/crnn.git
这个是 Convolutional Recurrent Neural Network (CRNN) 的 PyTorch 实现。CRNN 由一些CNN,RNN和CTC组成,常用于基于图像的序列识别任务,例如场景文本识别和OCR。 Scaling the Scattering Transform: Deep Hybrid Networks
https://github.com/edouardoyallon/pyscatwave.git
使用了“scattering network”的CNN实现,特别的构架提升了网络的效果。 Conditional Similarity Networks (CSNs)
https://github.com/andreasveit/conditional-similarity-networks.git
《Conditional Similarity Networks》的PyTorch实现。 Multi-style Generative Network for Real-time Transfer
https://github.com/zhanghang1989/PyTorch-Style-Transfer.git
MSG-Net 以及 Neural Style 的 PyTorch 实现。 Big batch training
https://github.com/eladhoffer/bigBatch.git
《Train longer, generalize better: closing the generalization gap in large batch training of neural networks》的 PyTorch 实现。 CortexNet
https://github.com/e-lab/pytorch-CortexNet.git
一个使用视频训练的鲁棒预测深度神经网络。 Neural Message Passing for Quantum Chemistry
https://github.com/priba/nmp_qc.git
论文《Neural Message Passing for Quantum Chemistry》的PyTorch实现,好像是讲计算机视觉下的神经信息传递。
对抗生成网络、生成模型、GAN相关实现 Generative Adversarial Networks (GANs) in PyTorch
https://github.com/devnag/pytorch-generative-adversarial-networks.git
一个非常简单的由PyTorch实现的对抗生成网络 DCGAN & WGAN with Pytorch
https://github.com/chenyuntc/pytorch-GAN.git
由中国网友实现的DCGAN和WGAN,代码很简洁。 Official Code for WGAN
https://github.com/martinarjovsky/WassersteinGAN.git
WGAN的官方PyTorch实现。 DiscoGAN in PyTorch
https://github.com/carpedm20/DiscoGAN-pytorch.git
《Learning to Discover Cross-Domain Relations with Generative Adversarial Networks》的 PyTorch 实现。 Adversarial Generator-Encoder Network
https://github.com/DmitryUlyanov/AGE.git
《Adversarial Generator-Encoder Networks》的 PyTorch 实现。 CycleGAN and pix2pix in PyTorch
https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix.git
图到图的翻译,著名的 CycleGAN 以及 pix2pix 的PyTorch 实现。 Weight Normalized GAN
https://github.com/stormraiser/GAN-weight-norm.git
《On the Effects of Batch and Weight Normalization in Generative Adversarial Networks》的 PyTorch 实现。
机器翻译、问答系统、NLP相关实现 DeepLearningForNLPInPytorch
https://github.com/rguthrie3/DeepLearningForNLPInPytorch.git
一套以 NLP 为主题的 PyTorch 基础教程。本教程使用Ipython Notebook编写,看起来很直观,方便学习。 Practial Pytorch with Topic RNN & NLP
https://github.com/spro/practical-pytorch
以 RNN for NLP 为出发点的 PyTorch 基础教程,分为“RNNs for NLP”和“RNNs for timeseries data”两个部分。 PyOpenNMT: Open-Source Neural Machine Translation
https://github.com/OpenNMT/OpenNMT-py.git
一套由PyTorch实现的机器翻译系统。(包含,Attention Model) Deal or No Deal? End-to-End Learning for Negotiation Dialogues
https://github.com/facebookresearch/end-to-end-negotiator.git
Facebook AI Research 论文《Deal or No Deal? End-to-End Learning for Negotiation Dialogues》的 PyTorch 实现。 Attention is all you need: A Pytorch Implementation
https://github.com/jadore801120/attention-is-all-you-need-pytorch.git
Google Research 著名论文《Attention is all you need》的PyTorch实现。Attention Model(AM)。 Improved Visual Semantic Embeddings
https://github.com/fartashf/vsepp.git
一种从图像中检索文字的方法,来自论文:《VSE++: Improved Visual-Semantic Embeddings》。 Reading Wikipedia to Answer Open-Domain Questions
https://github.com/facebookresearch/DrQA.git
一个开放领域问答系统DrQA的PyTorch实现。 Structured-Self-Attentive-Sentence-Embedding
https://github.com/ExplorerFreda/Structured-Self-Attentive-Sentence-Embedding.git
IBM 与 MILA 发表的《A Structured Self-Attentive Sentence Embedding》的开源实现。
先进视觉推理系统 Visual Question Answering in Pytorch
https://github.com/Cadene/vqa.pytorch.git
一个PyTorch实现的优秀视觉推理问答系统,是基于论文《MUTAN: Multimodal Tucker Fusion for Visual Question Answering》实现的。项目中有详细的配置使用方法说明。 Clevr-IEP
https://github.com/facebookresearch/clevr-iep.git
Facebook Research 论文《Inferring and Executing Programs for Visual Reasoning》的PyTorch实现,讲的是一个可以基于图片进行关系推理问答的网络。
深度强化学习相关实现 Deep Reinforcement Learning withpytorch & visdom
https://github.com/onlytailei/pytorch-rl.git
多种使用PyTorch实现强化学习的方法。 Value Iteration Networks in PyTorch
https://github.com/onlytailei/Value-Iteration-Networks-PyTorch.git
Value Iteration Networks (VIN) 的PyTorch实现。 A3C in PyTorch
https://github.com/onlytailei/A3C-PyTorch.git
Adavantage async Actor-Critic (A3C) 的PyTorch实现。
通用神经网络高级应用
PyTorch-meta-optimizer
https://github.com/ikostrikov/pytorch-meta-optimizer.git
论文《Learning to learn by gradient descent by gradient descent》的PyTorch实现。 OptNet: Differentiable Optimization as a Layer in Neural Networks
https://github.com/locuslab/optnet.git
论文《Differentiable Optimization as a Layer in Neural Networks》的PyTorch实现。 Task-based End-to-end Model Learning
https://github.com/locuslab/e2e-model-learning.git
论文《Task-based End-to-end Model Learning》的PyTorch实现。 DiracNets
https://github.com/szagoruyko/diracnets.git
不使用“Skip-Connections”而搭建特别深的神经网络的方法。 ODIN: Out-of-Distribution Detector for Neural Networks
https://github.com/ShiyuLiang/odin-pytorch.git
这是一个能够检测“分布不足”(Out-of-Distribution)样本的方法的PyTorch实现。当“true positive rate”为95%时,该方法将DenseNet(适用于CIFAR-10)的“false positive rate”从34.7%降至4.3%。 Accelerate Neural Net Training by Progressively Freezing Layers
https://github.com/ajbrock/FreezeOut.git
一种使用“progressively freezing layers”来加速神经网络训练的方法。 Efficient_densenet_pytorch
https://github.com/gpleiss/efficient_densenet_pytorch.git
DenseNets的PyTorch实现,优化以节省GPU内存。
人工智能
2019-03-09 07:39:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
项目简介:
最近在做一个有趣的项目,需要对某网站的验证码进行识别。
某网站验证码如图: ,像素大小:30x106x3
通过人工标记的验证码数量约为1000条:
现在需要通过机器学习方法来进行识别新验证码,设计的方案有如下四种: KNN + 原样本图;需要对图像去噪、二值化、切割等处理。对数据量要求没CNN高。 CNN + 原样本图;缺点:样本少,优点:数据质量高。 CNN + 构造类似验证码图;缺点:构造验证码是否和和原验证码类似,需要较高技术;优点:样本多。 CNN + 单字符样本图;优点:输入图像小,且输出类别少。 其他:如用pytesseract+去噪+二值化等,简单尝试了一下准确率很低,pass掉了
方案一:KNN + 原样本图
步骤: 去噪: 原图: class NoiseDel(): #去除干扰噪声 def noise_del(self,img): height = img.shape[0] width = img.shape[1] channels = img.shape[2] # 清除四周噪点 for row in [0,height-1]: for column in range(0, width): if img[row, column, 0] == 0 and img[row, column, 1] == 0: img[row, column, 0] = 255 img[row, column, 1] = 255 for column in [0,width-1]: for row in range(0, height): if img[row, column, 0] == 0 and img[row, column, 1] == 0: img[row, column, 0] = 255 img[row, column, 1] = 255 # 清除中间区域噪点 for row in range(1,height-1): for column in range(1,width-1): if img[row, column, 0] == 0 and img[row, column, 1] == 0: a = img[row - 1, column] # 上 b = img[row + 1, column] # 下 c = img[row, column - 1] # 左 d = img[row, column + 1] # 右 ps = [p for p in [a, b, c, d] if 1 < p[1] < 255] # 如果上下or左右为白色,设置白色 if (a[1]== 255 and b[1]== 255) or (c[1]== 255 and d[1]== 255): img[row, column, 0] = 255 img[row, column, 1] = 255 # 设置灰色 elif len(ps)>1: kk = np.array(ps).mean(axis=0) img[row, column, 0] = kk[0] img[row, column, 1] = kk[1] img[row, column, 2] = kk[2] else: img[row, column, 0] = 255 img[row, column, 1] = 255 return img # 灰度化 def convert2gray(self,img): if len(img.shape) > 2: gray = np.mean(img, -1) # 上面的转法较快,正规转法如下 # r, g, b = img[:,:,0], img[:,:,1], img[:,:,2] # gray = 0.2989 * r + 0.5870 * g + 0.1140 * b return gray else: return img # 二值化 def binarizing(self,img,threshold, cov=False): w, h = img.shape if cov: for y in range(h): for x in range(w): if img[x, y] > threshold: img[x, y] = 0 else: img[x, y] = 255 else: for y in range(h): for x in range(w): if img[x, y] < threshold: img[x, y] = 0 else: img[x, y] = 255 return img
去噪后: 切分最小图 def cut_box(img,resize=(64,18)): # 灰度,二值化 image = nd.convert2gray(img) image = nd.binarizing(image,190, True) image = Image.fromarray(image) img0 = Image.fromarray(img) box = image.getbbox() box1 = (box[0]-2,box[1]-2,box[2]+2,box[3]+2) image = img0.crop(box1) image = image.resize(resize) return np.array(image)
切分后: 分割字符串: def seg_img(img): h,w,c = img.shape d = int(w/4) img_list = [] for i in range(4): img_list.append(img[:,i*d:(i+1)*d]) return img_list
分割后: , , ,
经过对1000张标记好的图片进行处理,得到各个字母数字对应的单字符图片数据集: KNN训练及预测:
对图像进行灰度处理 import os from PIL import Image import numpy as np from cut_prc import cut_box,seg_img from noise_prc import NoiseDel from sklearn import neighbors, svm,tree,linear_model from sklearn.model_selection import train_test_split nd = NoiseDel() def predict_img(img, clf): text = '' image = nd.noise_del(img) image = cut_box(image) image_list = seg_img(image) for im in image_list: im = nd.convert2gray(im) im = im.reshape(-1) c = clf.predict([im,])[0] text += c return text if __name__=="__main__": # 获取训练数据 path = 'data/png_cut' classes = os.listdir(path) x = [] y = [] for c in classes: c_f = os.path.join(path, c) if os.path.isdir(c_f): files = os.listdir(c_f) for file in files: img = Image.open(os.path.join(c_f, file)) img = np.array(img) img = nd.convert2gray(img) img = img.reshape(-1) x.append(img) y.append(c.replace('_','')) x = np.array(x) y = np.array(y) # 拆分训练数据与测试数据 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.02) # 训练KNN分类器 clf = neighbors.KNeighborsClassifier(n_neighbors=5) clf.fit(x_train, y_train) # 预测测试集 test_pre = clf.predict(x_test) print("KNN accuracy score:", (test_pre == y_test).mean()) # 预测新样本集 newpath = 'data/png_new' newfiles = os.listdir(newpath) for file in newfiles: image = Image.open(os.path.join(newpath,file)) image = np.array(image) text = predict_img(image, clf) print(text) # # 训练svm分类器 # clf = svm.LinearSVC() ### # clf.fit(x_train, y_train) # # test_pre = clf.predict(x_test) # print("SVM accuracy score:", (test_pre == y_test).mean()) # # # 训练dt分类器 # clf = tree.DecisionTreeClassifier() # clf.fit(x_train, y_train) # # test_pre = clf.predict(x_test) # print("DT accuracy score:", (test_pre == y_test).mean()) # # # 训练lr分类器 # clf = linear_model.LogisticRegression() ### t # clf.fit(x_train, y_train) # # test_pre = clf.predict(x_test) # print("LR accuracy score:", (test_pre == y_test).mean()) 运行结果:(单个字符预测精度),KNN最高,达到80%,而SVM,DT,LR均较低 KNN accuracy score: 0.8170731707317073 SVM accuracy score: 0.6341463414634146 DT accuracy score: 0.4878048780487805 LR accuracy score: 0.5975609756097561
KNN 预测图片: mHFM crdN wa5Y swFn ApB9 eBrN rJpH fd9e kTVt t7ng
方案二:CNN+原样本图
步骤: 处理样本数据1020张图,灰度化 ,像素大小30*106,标签为小写字符(标记人员太懒了); 拆分数据:train:80%, val:20% 网络模型:输入数据维度30*106,采用三层CNN,每一层输出特征维数分别:16,128,16,FC层输出 512维,最后全连接输出4x63,每行代表预测字符的概率。 结果:验证集字符准确率最高到达了50%
方案三: CNN+ 构造类似验证码图
第三方库生成的验证码如下所示: from captcha.image import ImageCaptcha # pip install captcha
下载相应的字体(比较难找),然后修改第三方库中image.py文件,修改了第三方库后生成的验证码:
效果和我们需要的验证码比较相似了,但还是有区别。 fonts = ["font/TruenoBdOlIt.otf", "font/Euro Bold.ttf", "STCAIYUN.TTF"] image = ImageCaptcha(width=106, height=30,fonts=[fonts[0]],font_sizes=(18,18,18)) captcha = image.generate(captcha_text)
image.py 略..
采用自动生成的验证码,用于CNN训练模型,训练和验证精度都达到了98%,但测试原图1000样本的字符精度最高只有40%,由此可见,生成的验证码还是与目标验证码相差较大。 step: 18580/20000... loss: 0.0105... step: 18600/20000... loss: 0.0121... step: 18600/20000... --------- val_acc: 0.9675 best: 0.9775 --------- test_acc2: 0.4032 step: 18620/20000... loss: 0.0131... step: 18640/20000... loss: 0.0139... step: 18660/20000... loss: 0.0135... step: 18680/20000... loss: 0.0156... step: 18700/20000... loss: 0.0109... step: 18700/20000... --------- val_acc: 0.9625 best: 0.9775 --------- test_acc2: 0.3995
方案四: CNN+ 字符样本集
由于只有1000样本,直接经过CNN端到端输出字符序列,很难到达精度要求,为此方案三采用自动创建样本集的方法,但样本质量和真实样本之间存在差异,导致预测不准。为此,将原1000样本进行分割处理为单字符集,样本数量约4000左右,且输入维度减小很多,同时输出类别也减小很多。分析后改方案有一定可行性。
样本集处理与之前KNN一样: 经过对1000张标记好的图片进行处理,得到各个字母数字对应的单字符图片数据集: import os import numpy as np import tensorflow as tf from PIL import Image from noise_prc import NoiseDel from cut_prc import cut_box,seg_img from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelBinarizer nd = NoiseDel() class Config(): file_name = 'char_02' # 存放模型文件夹 w_alpha = 0.01 #cnn权重系数 b_alpha = 0.1 #cnn偏执系数 image_h = 18 image_w = 16 cnn_f = [16,32,32,512] # [cov1输出特征维度,cov2输出特征维度,cov3输出特征维度,全连接层输出维度] max_captcha = 1 #验证码最大长度 char_set_len = 50 #字符集长度 lr = 0.001 batch_size = 32 # 每批训练大小 max_steps = 200000 # 总迭代batch数 log_every_n = 20 # 每多少轮输出一次结果 save_every_n = 100 # 每多少轮校验模型并保存 class Model(): def __init__(self, config): self.config = config self.input() self.cnn() # 初始化session self.saver = tf.train.Saver() self.session = tf.Session() self.session.run(tf.global_variables_initializer()) def input(self): self.X = tf.placeholder(tf.float32, [None, self.config.image_h * self.config.image_w]) self.Y = tf.placeholder(tf.float32, [None, self.config.max_captcha * self.config.char_set_len]) self.keep_prob = tf.placeholder(tf.float32) # dropout # 两个全局变量 self.global_step = tf.Variable(0, trainable=False, name="global_step") self.global_loss = tf.Variable(0, dtype=tf.float32, trainable=False, name="global_loss") def cnn(self): x = tf.reshape(self.X, shape=[-1, self.config.image_h , self.config.image_w, 1]) # 3 conv layer w_c1 = tf.Variable(self.config.w_alpha * tf.random_normal([3, 3, 1, self.config.cnn_f[0]])) b_c1 = tf.Variable(self.config.b_alpha * tf.random_normal([self.config.cnn_f[0]])) conv1 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(x, w_c1, strides=[1, 1, 1, 1], padding='SAME'), b_c1)) conv1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') conv1 = tf.nn.dropout(conv1, self.keep_prob) w_c2 = tf.Variable(self.config.w_alpha * tf.random_normal([3, 3, self.config.cnn_f[0], self.config.cnn_f[1]])) b_c2 = tf.Variable(self.config.b_alpha * tf.random_normal([self.config.cnn_f[1]])) conv2 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv1, w_c2, strides=[1, 1, 1, 1], padding='SAME'), b_c2)) conv2 = tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') conv2 = tf.nn.dropout(conv2, self.keep_prob) w_c3 = tf.Variable(self.config.w_alpha * tf.random_normal([3, 3, self.config.cnn_f[1], self.config.cnn_f[2]])) b_c3 = tf.Variable(self.config.b_alpha * tf.random_normal([self.config.cnn_f[2]])) conv3 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv2, w_c3, strides=[1, 1, 1, 1], padding='SAME'), b_c3)) conv3 = tf.nn.max_pool(conv3, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') conv3 = tf.nn.dropout(conv3, self.keep_prob) # Fully connected layer h =tf.cast( conv3.shape[1],tf.int32) w = tf.cast( conv3.shape[2],tf.int32) f = tf.cast( conv3.shape[3],tf.int32) w_d = tf.Variable(self.config.w_alpha * tf.random_normal([h* w * f, self.config.cnn_f[3]])) b_d = tf.Variable(self.config.b_alpha * tf.random_normal([self.config.cnn_f[3]])) dense = tf.reshape(conv3, [-1, w_d.get_shape().as_list()[0]]) dense = tf.nn.relu(tf.add(tf.matmul(dense, w_d), b_d)) dense = tf.nn.dropout(dense, self.keep_prob) w_out = tf.Variable(self.config.w_alpha * tf.random_normal([self.config.cnn_f[3], self.config.max_captcha * self.config.char_set_len])) b_out = tf.Variable(self.config.b_alpha * tf.random_normal([self.config.max_captcha * self.config.char_set_len])) out = tf.add(tf.matmul(dense, w_out), b_out) # out = tf.nn.softmax(out) # loss # loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(output, Y)) self.loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=out, labels=self.Y)) # optimizer 为了加快训练 learning_rate应该开始大,然后慢慢衰 self.optimizer = tf.train.AdamOptimizer(learning_rate=self.config.lr).minimize(self.loss,global_step=self.global_step) predict = tf.reshape(out, [-1, self.config.max_captcha, self.config.char_set_len]) self.max_idx_p = tf.argmax(predict, 2) max_idx_l = tf.argmax(tf.reshape(self.Y, [-1, self.config.max_captcha, self.config.char_set_len]), 2) correct_pred = tf.equal(self.max_idx_p, max_idx_l) self.accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32)) def load(self, checkpoint): self.saver.restore(self.session, checkpoint) print('Restored from: {}'.format(checkpoint)) def train(self, get_next_batch, model_path, x_train, y_train, x_test, y_test): with self.session as sess: while True: batch_x, batch_y = get_next_batch(x_train, y_train,self.config.batch_size) _, loss_ = sess.run([self.optimizer, self.loss], feed_dict={self.X: batch_x, self.Y: batch_y, self.keep_prob: 0.75}) if self.global_step.eval() % self.config.log_every_n == 0: print('step: {}/{}... '.format(self.global_step.eval(), self.config.max_steps), 'loss: {:.4f}... '.format(loss_)) # 每100 step计算一次准确率 if self.global_step.eval() % self.config.save_every_n == 0: # batch_x_test, batch_y_test = get_next_batch(100) acc = sess.run(self.accuracy, feed_dict={self.X: x_test, self.Y: y_test, self.keep_prob: 1.}) print('step: {}/{}... '.format(self.global_step.eval(), self.config.max_steps), '--------- acc: {:.4f} '.format(acc), ' best: {:.4f} '.format(self.global_loss.eval())) if acc > self.global_loss.eval(): print('save best model...') update = tf.assign(self.global_loss, acc) # 更新最优值 sess.run(update) self.saver.save(sess, os.path.join(model_path, 'model'), global_step=self.global_step) if self.global_step.eval() >= self.config.max_steps: #self.saver.save(sess, os.path.join(model_path, 'model_last'), global_step=self.global_step) break def test(self, batch_x_test): sess = self.session max_idx_p = sess.run(self.max_idx_p, feed_dict={self.X: batch_x_test, self.keep_prob: 1.}) return max_idx_p def get_next_batch( train_x, train_y, batch_size=32): n = train_x.shape[0] chi_list = np.random.choice(n, batch_size) return train_x[chi_list],train_y[chi_list] def img_cut_to_arry(img): imgs = [] image = nd.noise_del(img) image = cut_box(image) image_list = seg_img(image) for im in image_list: im = nd.convert2gray(im) im = im.reshape(-1) imgs.append(im) return imgs if __name__=="__main__": # nd = NoiseDel() # 获取训练数据 path = 'data/png_cut' classes = os.listdir(path) x = [] y = [] for c in classes: c_f = os.path.join(path, c) if os.path.isdir(c_f): files = os.listdir(c_f) for file in files: img = Image.open(os.path.join(c_f, file)) img = np.array(img) img = nd.convert2gray(img) img = img.reshape(-1) x.append(img) y.append(c.replace('_','')) lb = LabelBinarizer() ly = lb.fit_transform(y) # one-hot x = np.array(x) y = np.array(ly) # 拆分训练数据与测试数据 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.02) # 创建模型目录 model_path = os.path.join('c_models', Config.file_name) if os.path.exists(model_path) is False: os.makedirs(model_path) # 加载上一次保存的模型 model = Model(Config) checkpoint_path = tf.train.latest_checkpoint(model_path) if checkpoint_path: model.load(checkpoint_path) # train and val print('start to training...') model.train(get_next_batch, model_path, x_train,y_train, x_test, y_test) # test # 预测新样本集 newpath = 'data/png_new' newfiles = os.listdir(newpath) for file in newfiles: pre_text='' image = Image.open(os.path.join(newpath,file)) image = np.array(image) imgs= img_cut_to_arry(image) for img in imgs: p = model.test([img,]) p_arr = np.zeros([1,50]) p_arr[0,p] =1 c = lb.inverse_transform(p_arr) pre_text += c[0] print(pre_text) 运行结果:字符预测精度95%以上 step: 2500/200000... loss: 0.0803... step: 2500/200000... --------- acc: 0.0854 best: 0.1341 step: 2520/200000... loss: 0.0818... step: 2540/200000... loss: 0.0844... step: 2560/200000... loss: 0.0827... step: 2580/200000... loss: 0.0794... step: 2600/200000... loss: 0.0823... step: 2600/200000... --------- acc: 0.1951 best: 0.1341 save best model... step: 2620/200000... loss: 0.0775... step: 2640/200000... loss: 0.0754... step: 2660/200000... loss: 0.0823... step: 2680/200000... loss: 0.0678... step: 2700/200000... loss: 0.0763... step: 2700/200000... --------- acc: 0.3049 best: 0.1951 . . . . step: 41400/200000... --------- acc: 0.8659 best: 0.9512 step: 41450/200000... loss: 0.0091... step: 41500/200000... loss: 0.0134... step: 41550/200000... loss: 0.0151... step: 41600/200000... loss: 0.0256... step: 41600/200000... --------- acc: 0.9390 best: 0.9512
预测图片: mHPM srdN wa5Y eWpn AgB9 eHr8 rJpH fd9e bTYt tTwg
最后,附上源码地址: github
人工智能
2019-03-08 17:12:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
深度学习与处理用于数据驱动的地球系统科学
由Markus Reichstein 在 2019 发表于 《Nature》。
这是一篇综述性文章,介绍了机器学习如何在地学中的应用与挑战。地球系统科学进入了大数据时代。地球系统数据就是典型的大数据,具备大数据四大特征:volume, velocity, variety and veracity(体积,速度,多样性和准确性),例如各种遥感、定点观测、模式数据。如今面临挑战就是如何从这些大数据中提取并解读信息,因为信息收集速度远大于我们所能消化的速度。数据的增多并未带对系统预测能力的提高,我们需要对数据进行理解。在这种背景下,机器学习就是我们很好的机遇。
文章从以几方面具体展开论述:
(1)地学中最先进的机器学习 。诸如神经网络、随机森林方法很早就应用于地学中的分类、变化检测、土壤制图问题。但这些应用是针对空间,在时间上是相对静态的,但地球是不断变化的。机器学习回归方法在时间动态上具有优势,比如具有隐含层的人工神经网络,可预测碳通量在时间与空间上的变化。但这些应用也存在一些问题需要注意,比如外推能力,抽样或数据偏见,忽视混杂因素,统计关联与因果关系等。经典的机器学习方法需要一些先验知识确定一些时空相关feature,而不能自动探索数据的时空特征。一些时空动态特征比如“记忆效应”可以作为feature手动加入到传统机器学习中,但最新的深度学习已经没有这些限制。
(2)深度学习在地球系统科学中的机遇。 深度学习已在其他领域得到了众多应用,但在地学中的应用还处于初级阶段。已有一些研究显示深度学习可以很好的提取时空特征,比如极端天气,而不需要很多人类干预。这也可用于城市变化的遥感自动提取。深度学习方法通常被划分为空间学习(例如,用于对象分类的卷积神经网络)和序列学习(例如,语音识别),但两者逐渐融合,可应用视频与动作识别问题。这些问题类似于地学中随时间变化的多维度结构,例如有序降水对流与植被状态。虽然有很大应用前景,但应用于时空变化的大气海洋传输或植被动态还有待发展。
(3)深度学习在地球系统科学中的挑战。 虽然传统深度学习的应用对象与地学现象有很大相似性,但也存在重要区别。比如高光谱、多波段就比基于三原色RGB的计算机图像识别复杂很多,此外还有带噪音、有缺测的卫星数据。另外,波段、时间与空间维度的集合也会带来计算量的挑战。计算机图片中识别可大量“狗”,“猫”现成训练样本,而地学中没有类似被标记的大量训练样本,如干旱。对外,作者总结出五大挑战,分别来自可解释性、物理一致性、数据的复杂与确定性、缺少标记样本、以及计算需求。若这些挑战能解决,那么深度学习将对地学带来巨大改变。近期最有前景的应用是”临近预报“(nowcasting),未来是长期预测。作者认为深度学习将很快成为地学中分类与时空预测问题的主要方法。
(4) 与物理建模集成。 物理建模(理论驱动)与机器学习建模(数据驱动)过去往往被认为是两个领域,具有不同范式。但其实两种方法可以相互补充的,前者外推能力强,后者更灵活可发现新规律。作者提出二种方法可结合的几个潜在点:改善参数化、用机器学习“替代”物理模型中子模块、模型与观测的不匹配分析,约束子模型、代替模型或仿真。
(5)推动科学发展。 机器学习方法无疑给分类和预测问题带来大幅提高。机器学习的数据驱动方法还可从数据中挖掘出过去不知道的新信息,从而推动新机制新认识的产生。
(6)结语。 地球科学大数据时代机器学习很有用,但也存在应用挑战,作者对此提出四点建议:识别数据的特殊性、推论的合理性和可解释性、不确定性估计、针对复杂物理模式进行验证。未来过程模型与机器学习将进一步结合。数据驱动的机器学习不会替代物理模型,但是会起到补充和丰富的作用,最终实现混合建模。
第一作者Markus Reichstein是大牛,单位是1 Department of Biogeochemical Integration, Max Planck Institute for Biogeochemistry, Jena, Germany. 2 Michael-Stifel-Center Jena for Data-driven and Simulation Science, Jena, Germany. 来源, https://mp.weixin.qq.com/s/uL4C3birbbFQ-UhntuTgRg 英文, https://www.nature.com/articles/s41586-019-0912-1
人工智能
2019-03-08 10:27:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Hanlp在离线环境下的安装我是没有尝试过的,分享SunJW_2017的这篇文章就是关于如何在离线环境下安装hanlp的。我们可以一起来学习一下!
HanLP是一款优秀的中文自然语言处理工具,可以实现包括分词、词性标注、实体识别在内容诸多功能,详情见其项目主页。另外,该工具包还提供了python3的接口,在线安装很方便,但有时需要部署在内网机等没有网络环境的机器上,比较繁琐,整理步骤如下:
1、安装jpype1,这是pyhanlp的依赖包,可以下载编译好的.whl文件,地址在这,选择对应自己python版本和操作系统版本的后,用pip install *.whl进行安装即可。
2、安装java环境,由于HanLP是用java开发的,因此调用python的接口时机器上应该配置了java环境,可以在网上搜索安装。
3、在pyhanlp的项目主页下载完整的.zip压缩包,解压后进入文件夹执行python setup.py install。
4、下载data-for-1.7.0.zip和hanlp-1.7.0.-release.zip,解压后分别获得data文件夹和hanlp.properties、hanlp-1.7.0.jar文件。
5、进入python包的安装目录,以Anaconda为例,进入该安装目录下的./lib/site-packages/pyhanlp-0.1.44-py3.6.egg/pyhanlp文件夹,将4中得到的文件复制到本目录,保证目录的内部结构如下:
hanlp
|—static
|  |—data
|  |  |—dictionary
|  |  |—model
|  |  |—READ.html
|  |  |—version.txt
|  |—init.py
|  |—hanlp.properties
|  |—hanlp.properties.in
|  |—hanlp-1.7.0.jar
|  |—index.html
|—init.py
|—main.py
|—server.py
|—util.py
6、编辑hanlp.properties中的内容,更改其中root=行的内容,使其指向data文件夹的上一层,如root=D:/Anaconda/Lib/site-packages/pyhanlp-0.1.44-py3.6.egg/pyhanlp/static。
7、打开命令行,输入hanlp -v,检查是否安装成功。正常应该返回jar包、data文件夹和hanlp.properties的位置。
---------------------

人工智能
2019-03-08 10:15:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
根据 Gartner 对全球 CIO 的调查结果显示,人工智能将成为 2019 年组织革命的颠覆性力量。对于人工智能来说,算力即正义,成本即能力,利用 Docker 和 Kubernetes 代表云原生技术为 AI 提供了一种新的工作模式,将 GPU 机器放到统一的资源池进行调度和管理,这避免了GPU 资源利用率低下和人工管理的成本。因此,全球主要的容器集群服务厂商 Kubernetes 都提供了 Nvidia GPU 容器集群调度能力,但是通常都是将一个 GPU 卡分配给一个容器。这虽然可以实现比较好的隔离性,确保使用 GPU 的应用不会被其他应用影响;对于深度学习模型训练的场景也非常适合,但是,针对模型开发和模型预测的场景还是会显得比较浪费。基于此,大家有了共享 GPU 的集群调度需求。
Kubernetes 共享 GPU 集群调度
共享 GPU 的集群调度就是能够让更多的模型开发和预测服务共享同一个 GPU 卡,进而提高集群中 Nvidia GPU 的利用率。而这就需要提供 GPU 资源的划分,而这里 GPU 资源划分的维度指的就是 GPU 显存和 Cuda Kernel 线程的划分。通常在集群级别谈支持共享 GPU 是以下两件事情:
1.调度
2.隔离,我们这里主要讨论的是调度,隔离的方案目前需要用户通过应用限制(比如使用 Tensorflow 的per_process_gpu_memory_fraction 来控制),未来会提供基于 Nvidia 的 MPS 的可选项, 也会考虑 GPU 的方案。
而对于细粒度的 GPU 卡调度,目前 Kubernetes 社区并没有很好的方案,这是由于 Kubernetes 对于 GPU 这类扩展资源的定义仅仅支持整数粒度的加加减减,无法支持复杂资源的分配。比如用户希望使用 Pod A 占用半张 GPU卡,这在目前 Kubernetes 的架构设计中无法实现资源分配的记录和调用。这里挑战是多卡 GPU 共享是实际矢量资源问题,而 Extened Resource 是标量资源的描述。
针对此问题,我们设计了一个 Out Of Tree 的共享 GPU 调度方案,该方案依赖于 Kubernetes 的现有的工作机制: Extended Resource 定义 Scheduler Extender 机制 Device Plugin 机制 Kubectl 的扩展机制
这个 GPU 共享调度扩展的好处是:利用 Kubernetes 的扩展和插件机制实现,对于 API Server,Scheduler,Controller Manager 以及 Kubelet 等核心组件没有侵入性。这就方便了使用者可以在不同 Kubernetes 版本上应用这个方案,无需 rebase 代码和重新构建 Kubernetes 二进制包。
用户场景 集群管理员:“我想提高集群的 GPU 使用率;在开发过程中,多个用户共享模型开发环境。” 应用开发人员:“我希望能够同时在 Volta GPU 上运行多个推理任务。”
[]( https://www.atatech.org/articles/132268#2) 目标 能够让使用者通过 API 描述对于一个可共享资源的申请, 并能实现该种资源的调度
[]( https://www.atatech.org/articles/132268#3) 非目标 不支持该共享资源的隔离 不支持超卖
[]( https://www.atatech.org/articles/132268#4) 设计原则 明确问题简化设计,第一步只负责调度和部署,后续再实现运行时显存管控。
有很多的客户明确的诉求是首先可以支持多AI应用可以调度到同一个 GPU 上,他们可以接受从应用级别控制显存的大小,利用类似 gpu_options.per_process_gpu_memory_fraction 控制应用的显存使用量。那我们要解决的问题就先简化到以显存为调度标尺,并且把显存使用的大小以参数的方式传递给容器内部。 不做侵入式修改
本设计中不会修改 Kubernetes 核心的 Extended Resource 的设计, Scheduler 的实现,Device Plugin 的机制以及 Kubelet 的相关设计。重用 Extended Resource 描述共享资源的申请 API。这样的好处在于提供一个可以移植的方案,用户可以在原生 Kubernetes 上使用这个方案。 按显存和按卡调度的方式可以在集群内并存,但是同一个节点内是互斥的,不支持二者并存;要么是按卡数目,要么是按显存分配。
详细设计
[]( https://www.atatech.org/articles/132268#6) 前提: 依旧延用 Kubernetes Extended Resource 定义,但是衡量维度最小单位从 1 个 GPU 卡变为 GPU 显存的 MiB。如果所节点使用的 GPU 为单卡 16GiB 显存,它对应的资源就是 16276MiB; 由于用户对于共享GPU的诉求在于模型开发和模型预测场景,在此场景下,用户申请的GPU资源上限不会超过一张卡,也就是申请的资源上限为单卡。
而我们的工作首先是定义了两个新的 Extended Resource: 第一个是 gpu-mem, 对应的是 GPU 显存;第二个是 gpu-count,对应的是 GPU 卡数。 通过两个标量资源描述矢量资源, 并且结合这一资源,提供支持共享 GPU 的工作机制。下面是基本的架构图:
[]( https://www.atatech.org/articles/132268#7) 核心功能模块: GPU Share Scheduler Extender : 利用 Kubernetes 的调度器扩展机制,负责在全局调度器 Filter 和 Bind 的时候判断节点上单个 GPU 卡是否能够提供足够的 GPU Mem,并且在 Bind 的时刻将 GPU 的分配结果通过 annotation 记录到 Pod Spec 以供后续 Filter 检查分配结果。 GPU Share Device Plugin : 利用 Device Plugin 机制,在节点上被 Kubelet 调用负责 GPU 卡的分配,依赖 scheduler Extender 分配结果执行。
[]( https://www.atatech.org/articles/132268#8) 具体流程: 资源上报
GPU Share Device Plugin 利用 nvml 库查询到 GPU 卡的数量和每张 GPU 卡的显存, 通过 ListAndWatch() 将节点的 GPU 总显存(数量 显存)作为另外 Extended Resource 汇报给 Kubelet; Kubelet 进一步汇报给 Kubernetes API Server。 举例说明,如果节点含有两块 GPU 卡,并且每块卡包含 16276MiB,从用户的角度来看:该节点的 GPU 资源为 16276 2 = 32552; 同时也会将节点上的 GPU 卡数量 2 作为另外一个 Extended Resource 上报。
2. 扩展调度
GPU Share Scheduler Extender 可以在分配 gpu-mem 给 Pod 的同时将分配信息以 annotation 的形式保留在 Pod spec 中,并且在过滤时刻根据此信息判断每张卡是否包含足够可用的 gpu-mem 分配。
2.1 Kubernetes 默认调度器在进行完所有过滤(filter)行为后会通过 http 方式调用 GPU Share Scheduler Extender的filter 方法, 这是由于默认调度器计算 Extended Resource 时,只能判断资源总量是否有满足需求的空闲资源,无法具体判断单张卡上是否满足需求;所以就需要由 GPU Share Scheduler Extender 检查单张卡上是否含有可用资源。
以下图为例, 在由 3 个包含两块 GPU 卡的节点组成的 Kubernetes 集群中,当用户申请 gpu-mem=8138 时,默认调度器会扫描所有节点,发现 N1 所剩的资源为 (16276 * 2 - 16276 -12207 = 4069 )不满足资源需求,N1 节点被过滤掉。
而 N2 和 N3 节点所剩资源都为 8138MiB,从整体调度的角度看,都符合默认调度器的条件;此时默认调度器会委托 GPU Share Scheduler Extender 进行二次过滤,在二次过滤中,GPU Share Scheduler Extender 需要判断单张卡是否满足调度需求,在查看 N2 节点时发现该节点虽然有 8138MiB 可用资源,但是落到每张卡上看,GPU0 和分别 GPU1 只有 4069MiB 的可用资源,无法满足单卡 8138MiB 的诉求。而 N3 节点虽然也是总共有 8138MiB 可用资源,但是这些可用资源都属于 GPU0,满足单卡可调度的需求。由此,通过 GPU Share Scheduler Extender 的筛选就可以实现精准的条件筛选。
2.2 当调度器找到满足条件的节点,就会委托 GPU Share Scheduler Extender 的 bind 方法进行节点和 Pod 的绑定,这里 Extender 需要做的是两件事情 以 binpack 的规则找到节点中最优选择的 GPU 卡 id,此处的最优含义是对于同一个节点不同的 GPU 卡,以 binpack 的原则作为判断条件,优先选择空闲资源满足条件但同时又是所剩资源最少的 GPU 卡,并且将其作为 ALIYUN_COM_GPU_MEM_IDX 保存到 Pod 的 annotation 中;同时也保存该 Pod 申请的 GPU Memory 作为 ALIYUN_COM_GPU_MEM_POD 和 ALIYUN_COM_GPU_MEM_ASSUME_TIME 保存至 Pod 的 annotation 中,并且在此时进行 Pod 和所选节点的绑定。 注意:这时还会保存 ALIYUN_COM_GPU_MEM_ASSIGNED 的 Pod annotation,它被初始化为“false”。它表示该 Pod 在调度时刻被指定到了某块 GPU 卡,但是并没有真正在节点上创建该 Pod。 ALIYUN_COM_GPU_MEM_ASSUME_TIME 代表了 指定 时间。
如果此时发现分配节点上没有 GPU 资源符合条件,此时不进行绑定,直接不报错退出,默认调度器会在 assume 超时后重新调度。 调用 Kubernetes API 执行节点和 Pod 的绑定
以下图为例,当 GPU Share Scheduler Extender 要把 gpu-mem:8138 的 Pod 和经过筛选出来的节点 N1 绑定,首先会比较不同 GPU 的可用资源,分别为 GPU0(12207),GPU1(8138),GPU2(4069),GPU3(16276),其中 GPU2 所剩资源不满足需求,被舍弃掉;而另外三个满足条件的 GPU 中, GPU1 恰恰是符合空闲资源满足条件但同时又是所剩资源最少的 GPU 卡,因此 GPU1 被选出。

3. 节点上运行
当 Pod 和节点绑定的事件被 Kubelet 接收到后,Kubelet 就会在节点上创建真正的 Pod 实体,在这个过程中, Kubelet 会调用 GPU Share Device Plugin 的 Allocate 方法, Allocate 方法的参数是 Pod 申请的 gpu-mem。而在 Allocate 方法中,会根据 GPU Share Scheduler Extender 的调度决策运行对应的 Pod 会列出该节点中所有状态为 Pending 并且 ALIYUN_COM_GPU_MEM_ASSIGNED 为 false 的 GPU Share Pod 选择出其中 Pod Annotation 的 ALIYUN_COM_GPU_MEM_POD 的数量与 Allocate 申请数量一致的 Pod。如果有多个符合这种条件的 Pod,就会选择其中 ALIYUN_COM_GPU_MEM_ASSUME_TIME 最早的 Pod。 将该 Pod 的 annotation ALIYUN_COM_GPU_MEM_ASSIGNED 设置为 true ,并且将 Pod annotation 中的 GPU 信息转化为环境变量返回给 Kubelet 用以真正的创建 Pod。
[]( https://www.atatech.org/articles/132268#9) 相关项目
目前项目已经开源到 github.com 上
gpushare-scheduler-extender
gpushare-device-plugin

部署
请参照 部署文档
[]( https://www.atatech.org/articles/132268#11) 测试样例 首先创建一个使用 aliyun.com/gpu-mem 的应用 apiVersion: apps/v1 kind: Deployment metadata: name: binpack-1 labels: app: binpack-1 spec: replicas: 1 selector: # define how the deployment finds the pods it manages matchLabels: app: binpack-1 template: # define the pods specifications metadata: labels: app: binpack-1 spec: containers: - name: binpack-1 image: cheyang/gpu-player:v2 resources: limits: # MiB aliyun.com/gpu-mem: 1024
使用
请参照 使用文档
构建
请参照 如何构建
视频 Demo
[]( https://www.atatech.org/articles/132268#15)Demo 1: 部署多个 GPU Share 的 Pod,发现他们以 binpack 的方式被放置到同一个 GPU 卡上
[]( https://www.atatech.org/articles/132268#16)Demo 2: 避免错误调度申请资源超过单个 GPU 可用资源的 Pod
Roadmap 在 Device Plugin 中提供 Nvidia MPS 的可选支持; 支持该方案可以在由 kubeadm 初始化的 Kubernetes 集群自动化部署; 提升 Scheduler Extener 的高可用性; 为 GPU, RDMA 和弹性网卡提供通用方案。
原文链接
人工智能
2019-03-07 16:45:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
前言:
搜索是人们在海量信息中获取有效信息的一种常见方式。
与日常“文字搜索”不同,图像搜索是通过“以图搜图”的方式来获取人们想要的图片信息。
当前,图像搜索正在以更广泛的应用、更形象的体验迅速崛起,获得越来越多的市场关注,被公认为当前最具有市场潜力的应用之一,并且在电子商务、知识产权保护、服装纺织、旅游等领域逐步得到广泛应用。
演讲嘉宾简介:
安永,阿里巴巴数据智能产品运营专家,来自阿里云智能事业群。
以下内容根据演讲嘉宾视频分享以及PPT整理而成。
本次主要内容分为三部分:
一、市场分析: 图像搜索被公认为最具市场潜力的应用之一。
二、产品介绍: 一图胜千言,从兴趣意念直达搜索目标。
三、用户分析: 图像搜索已经在各种行业领域有了广泛的应用。
一、市场分析
如果从市场角度去看,国内的电商,无论是巨头,譬如天猫、淘宝;还是垂直电商以及跨境电商类的平台越来越多,无论平台大小,这些都是我们今天图像搜索这款产品潜在的目标用户。
用户购买产品时对内容检索的需求是非常的强烈,要求也非常高,而且需要强调的一点是:他们的使用场景不会是在某个安静的环境去购买,在上下班路上、在逛超市的时候,有你喜欢的一款衣服,结果没有合适的码数,这个时候你打开淘宝,搜索框有个拍照按钮,拍张照片一搜,直接下单,第二天心仪的宝贝就到手了,你们说方便吗~~
这就是我们拍立淘这款工具,我们可以直接在天猫、淘宝里面检索相应图片,事实证明的话,拍立淘的购买转化率也会高15%左右。
另外就是国内的图库IP公司。我们拿到了04年到16年的一个数据,可以直接看到图片素材的交易量有了快速增长的趋势,国内也有很多这样的客户,包括视觉中国、东方IC…
在互联网上也有各种图片,譬如论坛,或者说旅游网站中那些图片也是属于我们图像搜索的范围内的,这些也都是我们的潜在客户!
二.图像搜索产品介绍
图像搜索服务 (Image Search) 是以深度学习和机器视觉技术为核心,结合不同行业应用和业务场景。
概览:
帮助用户在自建图库中实现相同或相似图片搜索的以图搜图服务。
我们产品是基于阿里巴巴电商拍立淘孵化出的搜索服务,提供低成本、高准确度、轻松交付的图像搜索服务!我们是基于阿里云IaaS底层,而且算法维护成本低,使用学习成本低,采用按月收费,同时 不限调用次数,不限调用次数,不限调用次数!
图像搜索是基于百亿级别的图片训练,我们算法毋庸置疑,尤其是在电商、零售领域是所向披靡。我们服务仅考虑客户图片总量大小和QPS数量,不做调用次数的收费,简单明了!
产品优势:
• 搜索精度高:业内领先水平的搜索服务。
• 搜索效率高:结合超大规模聚类和量化索引技术,达到毫秒级响应。
• 支持海量数据:大规模检索引擎可支持百亿级别数据。
• 实时化接口:支持实时增删数据。
• 支持定制化:可根据用户需求定制化开发。
三.用户分析
我们的目标客户前提必须要有大量的图片,这些图片不仅可以是摄影作品,也可以是各种商品。
我们能为客户解决的核心需求就是:商品搜索、图片查找、近似图片推荐等。
如上图所示,我们所能覆盖的各种类目,电商类目是我们最擅长的,其他类目的话我们也有很多成熟的案例,也是完全可以商业化的。
在这要极其强调一点:如果有以上这些类目外的需求,比如说汽车,我们也可以去做一些探索和定制。
图搜场景例举:
电商图库类场景:
简化搜索流程,提升购买体验
用户只需拍摄或者上传商品照片,就可以根据图片进行商品搜索。 省去了繁琐的文字描述,简化了商品搜索流程,大大提升用户的购物体验。
通用图库类场景:
高性价比,支持大并发服务
图片分享和社交类网站通常有大量通用图片供用户搜索使用,利用图像搜索服务,可在云端快速构建百亿级图像搜索引擎,提供以图搜图功能,提升用户体验。
最后说一下:
我们使用图搜要有两个很重要的流程:
1.要建索引库。 客户要把所有图片离线上传,把图片库传到阿里云上面做一个特征的提取,提取之后我们会建立一个检索引擎。
2.在线流程。 当新的图片过来后,我们要做类目识别、主体检测、特征提取,然后和大库里面原来建好的索引做匹配。
以上就是我们今天想要告诉大家的主要内容,如果还是没有理解图像搜索真正的需求在哪里,可以先思考以下三个问题试试:
1. 客户能否使用准确文字来描述想要找的产品?
2. 客户如何区分想要的产品上细节层面的不同?
3. 海外客户使用不同语言怎么去描述需求?
原文链接
人工智能
2019-03-07 16:01:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 2019 年是阿里云成立的第 10 年,在过去的 10 年间,阿里云引领了国内云基础设施市场;在当下,我们希望可以和您一起分享阿里云的新战略和新思考。
2019 年将是云原生在中国爆发和落地的一年,在这样的背景下,阿里将如何探索实时计算新架构?数据库的研发流程将如何演进?我们在代码智能化上又有怎样的思考和实践?云原生又将如何赋能AI、基因等各行业?
【开发者专场三大亮点】
亮点一
阿里巴巴集团副总裁/达摩院首席数据科学家/数据库产品事业部负责人 李飞飞
联合 阿里云云智能战略与合作部总经理 刘湘雯 共同畅谈开发者与可见的云未来。
亮点二
阿里云智能基础产品事业部研究员 周经森 发布 OpenJDK 长期支持版本 Alibaba Dragonwell
亮点三
重磅发布:CNCF X Alibaba 云原生技术课程
免费报名
https://www.yunqi.org/goPage?page=bj_signup_mb&activeId=2&ticketTypeId=39&channelId=23
【开发者专场议题】
原文链接
人工智能
2019-03-07 15:30:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 本文由云+社区发表 作者:Java3y
前言 只有光头才能变强
没错,这篇主要跟大家一起 入门 机器学习。作为一个开发者,”人工智能“肯定是听过的。作为一个开发面试者,肯定也会见过”机器学习“这个岗位(反正我校招的时候就遇到过)。
可能还会听过或者见过“深度学习”、“神经网络”等等这些非常火的 名词 ,那你对这些 术语 了解多少呢?
相信大家这几天在朋友圈也可以看到这照片:
核心AI代码 // 通过if else 以人工穷举的方式来假装实现智能机器人聊天 希望阅读完本文中后,大家可以对这些术语和机器学习有一定的了解。
一、术语介绍
首先我们来简单看看人工智能、深度学习、机器学习这些术语和它们之间的关系究竟是怎么样的。
1.1人工智能
不知道听到“人工智能”大家会联想到什么,可能大多数都会想到科幻电影的机器人。
《人工智能》电影的剧照
我们看来看看维基百科的定义: 人工智能(英语:Artificial Intelligence,缩写为 AI)亦称机器智能,指由 人制造出来的机器所表现出来的智能 。通常人工智能是指通过普通计算机程序的手段实现的人类智能技术。
人工智能也可以分成两类: 强人工智能:强人工智能观点认为“有可能”制造出“真正”能推理(Reasoning)和解决问题的智能机器,并且,这样的机器将
被认为是具有知觉、有自我意识的
。 像绝大多数科幻电影中的机器人就是在这范畴 弱人工智能:弱人工智能观点认为“不可能”制造出能“真正”地推理和解决问题的智能机器,这些机器只不过
“看起来”像是智能
的,但是并不真正拥有智能,也不会有自主意识。 我们 目前阶段 的人工智能,其实都是弱人工智能。
1.2机器学习
不知道听到“机器学习”大家会联想到什么。Emmm…反正我就是从字面的意思去理解:“机器可以 自我 学习”。
首先我们看一下维基百科是怎么说的: 机器学习是实现人工智能的一个途径 ,即以机器学习为手段解决人工智能中的问题。机器学习在近30多年已发展为一门多领域 交叉学科 ,涉及概率论、统计学、逼近论、凸分析、计算复杂性理论等多门学科
简单来说:机器学习可以通过 大量的数据或者以往的经验自动改进计算机程序/算法 。
什么是机器学习
生成完 模型f(x) 之后,我们将 样例数据丢进模型里边 ,就可以输出结果:
输入样例进模型,输出结果
我们说机器学习可以 自我 学习,是因为我们会将 样例数据也会丢到“历史数据”中 ,这样生成模型就会有一定的改动,从而达到“自我学习”的效果。
1.3它们之间的关系
等等,我们好像还没讲深度学习呢。我们从上面机器学习的介绍也可以知道,机器学习已发展为一门多领域 交叉学科 ,机器学习中就有 好多个经典的算法,其中就包含了神经网络(深度学习可看成是神经网络的升级版) 。由于近几年深度学习发展迅猛,一些特有的学习手段相继被提出,所以越来越多的人将其单独看作一种学习的方法。
《机器学习 周志华》: 所谓深度学习,狭义地说就是**“很多层”的神经网络**,在若干测试和竞赛下,尤其涉及语音、图像等复杂对象的引用中,深度学习取得优越的性能。
所以我们可以总结出人工智能、机器学习、深度学习之间的关系是这样的: 机器学习,是实现人工智能的重要方法。 深度学习,是实现机器学习的技术。
之间的关系
想要了解更多,可参考: 人工智能、机器学习和深度学习的区别? https://www.zhihu.com/question/57770020
二、机器学习入门
通过上面我们可以简单认为机器学习就是: 利用计算机 从历史数据找出 规律 ,把这些规律用到 未来 不确定场景的决策中。
下面我们再来学习一下机器学习的一些入门知识。
2.1机器学习的术语
特征、样本、数据集、标记这些术语的说明:
特征、样本、数据集、标记这些术语的说明
特征(属性)所张成的空间叫做 特征空间 。
特征空间 例如我们把“色泽”、"根蒂“、”敲声“作为三个坐标轴,则它们张成一个用于描述 西瓜的三围空间 ,每个西瓜都可在这个空间中找到自己的坐标位置。 由于空间中的每个点对应一个坐标向量,我们也把一个示例称为“特征向量 ”。
特征向量
回到我们上面的图,再来讲讲“训练数据”、“训练”、“标记”:
“训练数据”、“训练”、“标记”的术语解释
2.2机器学习的分类
一般机器学习又可以分成以下几类: 监督学习 半监督学习 非监督学习 增强学习
2.2.1监督学习
监督学习:训练数据(Training Data)可以告诉我们要找的那个模型的输入(Input)与输出(Output,也就是我们说的label)之间有什么样的关系。 给出的数据都有“答案”或“标记” 训练数据:"Java3y公众号"->好的公众号 , "Java4y公众号"->不好的公众号。 输出结果:好的公众号或者不好的公众号
在监听学习下又分为两种算法: 回归(Regression):结果是一个连续的 数值 (scalar),而非类别 分类(Classification):为训练数据进行分类别(多分类) 二分类:类别只有两种结果(YES OR NO)
回归例子 :知道前几天的PM2.5数值,预测一下明天的PM2.5数值。
回归例子
**二分类例子:**判断一封邮件是垃圾邮件还是正常邮件。
判断是垃圾邮件还是正常邮件
**多分类例子:**将新闻帖子分类成不同的类别。
分类成不同的类别
2.2.2非监督学习
非监督学习: 训练数据(Training Data)没有对应“答案”或“标记” 训练数据:"Java3y公众号" "Java4y公众号" "Java5y公众号" "Java6y公众号" "yyy公众号" "xxx公众号" "zzz公众号" 输出结果:("Java3y公众号" "Java4y公众号" "Java5y公众号" "Java6y公众号") ("yyy公众号" "xxx公众号" "zzz公众号") 分门类别
对没有“标记”的数据进行分类-聚类分析
对没有“标记”的数据进行分类-聚类分析
聚类分析例子: 在以前,中国移动有三个品牌:神州行、动感地带、全球通。我们给一堆的SIM卡交由学习算法训练, 不告诉它每张SIM卡具体是什么卡 ,最后我们是可以将这些SIM卡 分类别出来的 。
非监督学习的意义
非监督学习的意义
非监督学习的意义
2.2.3半监督学习
理解了监督学习和非监督学习,对于半监督学习就很容易理解了。
一部分数据有“标记”或者“答案”,另一部分数据没有 因为各种原因产生的标记缺失。
部分有label,部分没有label 通常都会使用非监督学习手段对数据进行处理(特征提取、降维),之后再只用监督学习手段做模型的训练和预测。
2.2.4增强学习 根据周围环境的情况,采取行动, 根据采取行动的结果,学习行动方式
增强学习
每次行动,就给这次的行动 评分 ,算法会根据评分来评估下一次的行动是好还是坏,最终不断改进。
给每次的行动评分
例子:Alpha Go下每步棋的时候都会 评估 自己这次下得怎么样,通过最终的结果不断改进下的每步棋。
2.3机器学习的其他分类
除了我们上面所说的监督学习、非监督学习、半监督学习、增强学习之外,机器学习也可以分成: 在线学习:
及时
将样例数据作为训练数据对模型进行训练。 需要加强对数据进行监控(有可能样本数据是脏数据,这样就破坏我们的模型) 离线(批量)学习:
定时
将样例数据作为训练数据对模型进行训练。 不能很快的适应环境的变化
还有: 参数学习:一旦学到了参数,就不再需要原有的数据集。通过调参数就好了。 非参数学习: 不对模型进行过多的假设 ,非参数不代表没参数。
最后
机器学习的核心在于算法上 ,这篇只是对机器学习的一个简单的入门,希望能对大家有所帮助。
此文已由腾讯云+社区在各渠道发布
获取更多新鲜技术干货,可以关注我们 腾讯云技术社区-云加社区官方号及知乎机构号
人工智能
2019-03-06 12:10:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
master分支
对于master分支,编译方法如下:
git clone https://github.com/hankcs/HanLP.git
mvn install -DskipTests

·由于目前一些test不够规范,使用了硬编码路径下的资源,所以暂时跳过单元测试。
·该方法不会将src/main/resources目录下的任何资源(包括hanlp.properties)打包进jar,如果需要打包资源文件,请切换到portable分支。
portable分支
git checkout portable
然后将需要的data放入src/main/resources,最后执行:

mvn install -DskipTests
运行jar
目前jar包中有一些模块可以命令行执行,以感知机词法分析器为例。由于这些模块一般需要加载外部data,所以需要在运行时指定hanlp.properties。运行时,一个典型的目录结构如下:
·此处只列出了重要的目录。
·一个良好的实践是把hanlp.properties放到resources目录下。

命令行需要指定jar包和hanlp.properties所在的目录:

$ java -cp target/hanlp-1.6.0.jar:src/main/resources com.hankcs.hanlp.model.perceptron.Main -test \
<<< '华安集团胡花蕊来到纽约艺术博物馆参观'
[华安/nz 集团/n]/nt 胡花蕊/nr 来到/v [纽约/ns 艺术/n 博物馆/n]/ns 参观/v

·Windows用户请使用分号java -cp target/hanlp-1.6.0.jar;src/main/resources
人工智能
2019-03-06 11:29:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
tensorflow模型转snpe模型
如果没有做到下面的要求,模型转换时有可能会出现:SNPE支持的操作,却提示转换失败,而且很多。
生成tensorflow模型时用的tensorflow版本和运行snpe转换工具时的tensorflow版本要保持一致
生成tensorflow模型时用的python版本和运行snpe转换工具时的python版本要保持一致
同一层的节点要在同一个命名空间下
全连接层要有偏置

使用tensorboard去查看模型时,模型较小时,可以使用Chrome,模型较大时,可以使用火狐

人工智能
2019-03-06 08:35:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
在“ 机器学习基础-假设空间、样本空间与归纳偏置 ”中提到了 归纳偏置实际上是一种模型选择策略, 尽管我们认为A模型更简单可能具有更好的泛化能力(更贴切实际问题对新数据的预测更准)而选择了A,但是实际情况中很可能会出现B模型比A更好的情况如图所示: (注:本文实际是对周志华西瓜书的部分总结)
黑点是训练数据,空心点是新数据,在(b)图中B模型比A模型更好。
也就是说在无数个模型中都可能会出现比A模型与实际数据更符合的情况(西瓜书中引入了NFL(没有免费的午餐定理)来着重说明 具体问题具体分析,这个具体问题实际上是指数据分布要与实际问题一致而不是指应用场景一致 ),换句话说哪个模型与实际情况更加符合我们就选择那个模型。
现在的问题是我们如何判断哪个模型与实际情况更加符合,因此引入了 模型的评估和选择 。
在评估和选择时,虽然使用了N种方法,但本质上还是将数据分成了训练集和测试集分别进行模型训练和模型验证,我们理想中的情况是训练集与测试集要同时与实际数据的概率分布一致,只有这样我们才能通过技术手段尽量选择到那个最优的模型,那N种方法直观上模型评估选择法,本质上是尽量保证与实际数据的概率分布一致!
人工智能
2019-03-05 20:46:00