[原创]DESTOON二次开发笔记(1)

mikel阅读(2253)

  • 获取模块分类:get_maincat()函数

求解get_maincat函数的用法,如get_maincat(0, $CATEGORY, 1),其中第一、二、三个参数分别表示什么,有谁知道,请介绍下,谢谢!

答:get_maincat()  三个参数,

第一个参数代表parentid

第二个参数代表所有的分类,指的是模块ID,而不是分类的ID

第三个参数 代表 分类的级别

如:$child = get_maincat(0, $CATEGORY, 1);则代表将parentid=0,分类级别为1的分类,存入到$child。

图片中所示的类别,都符合函数的调用结果,即上面的$child即调用图中所有的类别

可以给不同的分类归定不同的级别,差不多可以做的栏目用

get_maincat的函数的原型在\include\global.func.PHP文件中,我们还可以看到这个函数可以只使用两个函数,最后一个level有一个缺省值的,如果不规定这个值,就代表着分类下所有的子分类

function get_maincat($catid, $moduleid, $level = -1) {

global $db;

$condition = $catid ? “parentid=$catid” : “moduleid=$moduleid AND parentid=0″;

if($level >= 0) $condition .= ” AND level=$level”;

$cat = array();

$result = $db->query(“SELECT catid,catname,child,style,linkurl,item FROM {$db->pre}category WHERE $condition ORDER BY listorder,catid ASC”, ‘CACHE’);

while($r = $db->fetch_array($result)) {

$cat[] = $r;

}

return $cat;

}

 

  • 顶部用户登录:

万恶的destoon登录注册,有可能你在很苦恼的寻找了半天的调用方法,很不幸你失败了那么不用苦恼这里有最简单的调用方法
第一步在你的模版的头部(header.htm)里面默认的.js跟.css 不要删除,可以引入你自己制作的CSS、JS文件等等。
第二部还是在这个理 header.htm里面找到<div id=”destoon_member”></div>,这个html标签是存放 “游 客 欢迎 注册 登录 忘记密码”的div,记住id=”destoon_member”千万不能改,JavaScript就靠这个id来进行客户端 cookie检测的。
第三部缺一不可的第三部:尾部(footer.htm)最下面找到
<script type=”text/JavaScript”>show_task(‘{$destoon_task}’);</script>

  • 用户注册调试:
  1. 删除E:\UPUPW\htdocs\b2b\template\05zsdt12\member\register.htm中的
  2. 注册用户的处理流程:

E:\UPUPW\htdocs\b2b\member\register.php  à E:\UPUPW\htdocs\b2b\module\member\register.inc.php

  • if($submit) {
  • $do = new member; $do->add($post)
  • E:\UPUPW\htdocs\b2b\module\member\member.class.php add();
  • $member = $this->set_member($member);//获取post中的值赋值给$member的字段
  • $member_fields;//设置的会员的字段 增加的accounttype,需要添加到accounttype中
  • $company_fields;//设置的公司的字段 增加的usertype,需要添加到这里
  • 文章列表页面获取当前栏目的名称:

修改了E:\UPUPW\htdocs\b2b\template\05zsdt12\article\list.htm中的

调取E:\UPUPW\htdocs\b2b\include\global.func.php中的get_cat()函数,

调用{get_cat($CAT[‘catid’])}

$CAT变量的值:

array(22) {

[“catid”] => string(4)”1155″[“catname”] => string(12)”企业动态”[“style”] => string(0)””[“catdir”] => string(11)”qiyedongtai”[“linkurl”] => string(19)”list.php?catid=1155″[“letter”] => string(1)”q”[“level”] => string(1)”1″[“item”] => string(1)”0″[“property”] => string(1)”0″[“parentid”] => string(1)”0″[“arrparentid”] => string(1)”0″[“child”] => string(1)”0″[“arrchildid”] => string(4)”1155″[“listorder”] => string(4)”1155″[“template”] => string(0)””[“show_template”] => string(0)””[“SEO_title”] => string(12)”企业动态”[“SEO_keywords”] => string(12)”企业动态”[“seo_description”] => string(12)”企业动态”[“group_list”] => string(7)”3,5,6,7″[“group_show”] => string(7)”3,5,6,7″[“group_add”] => string(7)”3,5,6,7″

}

另外也可以自定义全局获取名称的函数:

include/global.func.php 加入以下函数

function get_catname ($catid) {
global $db;
$row = $db->get_one(“selec * from {$db->pre}category wher catid=$catid”);
return $row[‘catname’];
}

在循环标签中使用

{catname($t[catid])} 调用

在内容页使用 {catname($catid)} 调用

  • Destoon目录结构:

真正从零开始,TensorFlow详细安装入门图文教程! | 雷锋网

mikel阅读(1370)

帮你完成那个最难的从0到1

来源: 真正从零开始,TensorFlow详细安装入门图文教程! | 雷锋网

AI这个概念好像突然就火起来了,年初大比分战胜李世石的AlphaGo成功的吸引了大量的关注,但其实看看你的手机上的语音助手,相机上的人脸识别,今日头条上帮你自动筛选出来的新闻,还有各大音乐软件的歌曲“每日推荐”……形形色色的AI早已进入我们生活的方方面面。深刻的影响了着我们,可以说,这是一个AI的时代。

其实早在去年年底,谷歌就开源了其用来制作AlphaGo的深度学习系统Tensorflow,相信有不少同学曾经对着这款强大的机器学习系统蠢蠢欲动,但虽然有关Tensorflow的教程其实不少,甚至谷歌官方就在Tensorflow的官网给出了一份详细的教程,也有网站已经将其翻译成了中文(点击查看),但它仍然是有门槛的,尤其是对于对计算机及编程语言了解不深的同学,可能看着页面上凭空给出的代码陷入懵逼。

真正从零开始,TensorFlow详细安装入门图文教程!

而今天我要做的,就是带着所有这些几乎没有编程基础却很想学习Tensorflow的同学跨过这道坎。告诉你们大家如何准备好使用Tensorflow进行编程所需的一切,以及如何看懂教程上的那些代码所代表的含义,那么废话不多说,我们马上开始。

在Linux操作系统下的安装

安装环境

Tensorflow的支持列表里是没有Windows的。虽然可以用Docker来实现在Windows上运行,但小问题很多,它支持的最好的还是基于unix内核的系统,如Linux,因此我们最好还是安装一个Linux的环境来运行它。Linux是一款免费的开源操作系统,应用非常广泛,如著名的Android就是基于Linux改进的一款针对手机的操作系统。而对于我们来说,最易于理解的版本就是著名的Ubuntu,点击链接即可去官网下载,正如前面所说,下载和使用都是免费的。

如果你使用的是Mac,那就方便很多了,因为Mac os本身就是一个基于Unix的操作系统,已经搭载了全部安装Tensorflow所需要的组件。所以安装的很多步骤都可以省去,直接进行Tensorflow的安装,不过命令同Ubuntu有所不同。但你也可以看看接下来的教程,对理解那些命令也会有帮助。呃……你说你在Mac上装了Windows?

下载之后,你会得到一个装着Ubuntu系统的.iso文件。有两个办法来处理它,一是直接安装,同电脑现在在用的系统组成双系统(当然你也可以换掉现在的系统,不过我想应该没有人会愿意这么做的吧哈哈)。如果你不想那么大动干戈,也可以通过虚拟机来虚拟一个系统。不过,安装虚拟机对配置有一定要求,毕竟它相当于在你的电脑上同时打开两个系统了——CPU最好不要低于4代i3(尤其是笔记本,CPU型号的i3/5/7-xxxx的四位数里第一个x就表示它的代数)。内存——注意,内存一定不能低于4g,因为你给虚拟机分配的内存在虚拟机启动之后会1:1的从你的物理内存中划走。再加上物理机系统的消耗。当然,这个配置表是只有下限没有上限的,你的电脑配置越好,体验就越好。而装双系统的话,对配置的需求就小很多了。

真正从零开始,TensorFlow详细安装入门图文教程!

虚拟机安装中

网上相关的教程都比较多,在这里就不重复了,注意搜索安装双系统教程的时候要加上你现用的系统和你下载的Ubuntu系统的版本号。这里只讲几个需要注意的地方。

真正从零开始,TensorFlow详细安装入门图文教程!

因为Linux对安全性非常重视,因此不仅权限管理十分严格,在创建操作系统的时候也会要求你一定要输入一个密码,这个密码将用来登陆和获得root权限。就比如上面这个界面,如果你不把所有空格都填好是没法点下一步的。

Python

真正从零开始,TensorFlow详细安装入门图文教程!

Ubuntu桌面的样子,(悄悄说一句笔者觉得基于Unix的系统普遍比Windows好看太多,主要是字体看着真舒服)

安装好之后,我们看到了一些熟悉的软件和一些不熟悉的软件,我们先不去管它,介绍一下Python。Python是一种高级语言,它的特点是程序很简洁,但是因为简洁,所以在将其翻译成CPU可以理解的指令——也就是执行代码的时候速度会比那些低级一些的语言,比如C语言慢一些。不过在现在电脑的性能面前,这种速度的差别大多数时候根本不足挂齿。

解释器

很多人可能会觉得Python很抽象,因为提到Python,大家不会像C语言那样马上想起它有一个专用的编译器。Python可以执行的地方千奇百怪。甚至可以很方便的在系统的Terminal(一个类似于Windows里的命令行的工具)里直接执行。Ubuntu自带了Python,因此一般不用烦心安装事宜。

Tensorflow支持多种前端语言,但对Python的支持是最好的,因此我们的教程也基于Python来进行,首先我们打开Terminal。作为Ubuntu中非常重要的一个组成部分,有很多种方法可以打开它。比如在桌面上点击右键

真正从零开始,TensorFlow详细安装入门图文教程!

也可以点击左上角的那个Ubuntu图标搜索。打开后可以看到Terminal窗口如下所示。标题栏里@符号前面是你的用户名。

真正从零开始,TensorFlow详细安装入门图文教程!

如果你在你的计算机使用史中从来没有离开过图形用户界面(就是有一个鼠标和很多图标让你点的那种)。看到这个简单得吓人的窗口不要慌,只要输入正确的命令就好了。

在正式开始之前我想说:一定要注意窗口给出的提示(英文)。在实际操作中可能会碰到各种各样的问题,但常见的问题其实都可以根据它的报错信息找到原因,只要上网搜一搜相应的信息就能解决,甚至它自己就会给出解决的建议。如果你发现你的步骤一切正确,但就是无法成功,多试几次就好了,毕竟这些服务都是谷歌提供的,而谷歌……你懂的。

必不可少的python-pip和python-dev

在这个窗口中输入命令:

$ sudo apt-get install python-pip python-dev

注意,窗口中其实已经有一个$符号了,因此你在复制或者输入命令时其实不用将这个$符号也包括进去,但是网上的教程给出命令的时候一般是会把这个符号包括进去的,作为一个标志。注意一下就好。

命令最开始的sudo意味着这条指令将以root权限执行,所以需要输入你最开始设置的那个密码,注意输入过程在屏幕上是不会有任何体现的。输完直接按回车就行。

真正从零开始,TensorFlow详细安装入门图文教程!

输入后会出现一串代码,然后问是否继续,输入y回车

然后可以静待安装完成,解释一下这条命令:apt-get是从软件仓库中获取软件的一条命令,而软件仓库是Linux各大发行版的共有特征:它是一系列存放软件的服务器或网站,包含了软件包和索引文件,用户可以很轻松的使用命令自动定位并安装其中的软件,而省去了到处搜索的麻烦。install则是安装指令,而python-pip和python-dev则是两个需要安装的软件包的名字。pip可以理解成一个比较高级的软件安装器,安装Tensorflow要用到,而dev则是一个额外的类库,也是Tensorflow的安装和运行需要的。如果一切顺利,在大串英文划过后,我们会看到如下的界面:

真正从零开始,TensorFlow详细安装入门图文教程!

此时就可以安装Tensorflow了,指令如下:

$ sudo pip install –upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.8.0-cp27-none-linux_x86_64.whl

就像前面所说的,你可能会碰到这样那样的问题,比如下图这样的

真正从零开始,TensorFlow详细安装入门图文教程!

在这些时刻,不要慌张,仔细阅读错误信息,越往后的通常越重要,因为结论都是在最后给出的,像这个的最后:

真正从零开始,TensorFlow详细安装入门图文教程!

你看,它不仅告诉了你应该试着做什么,连怎么做都告诉你了。按它说的做就好

不过其实当时笔者用的并不是8.1.1版本,使用升级命令后也只是升级到了8.1.1版本,再次输入相同命令,它会告诉你你的版本已经是最新的了。但问题确实解决了,这条提示在之后没有再出现。

真正从零开始,TensorFlow详细安装入门图文教程!

更新程序将版本更新到了8.1.1,然后这个提示就不会再烦你了

再次输入安装Tensorflow的命令,如果不行,就多试几次,

真正从零开始,TensorFlow详细安装入门图文教程!

仔细看这些黄字的信息,会发现Network is unreachable这样的字样,如果你有什么传说中的利器的话,现在是时候拿出来用了。但是不用也没关系,多试几次,还是可以成功的。

真正从零开始,TensorFlow详细安装入门图文教程!

出现上图这样的界面的时候,你就可以长舒一口气,因为安装已经完成,现在你已经可以使用Tensorflow了,让我们跟着教程向世界说声hi吧。

从Terminal进入Python环境的方法也很简单,直接输入命令:Python。如果本机已经安装了Python,Terminal会显示Python的版本号等信息,同时下一个指令的前缀会由用户名等一串字符变成这样的东西:“>>>”,这说明进入完成了。

真正从零开始,TensorFlow详细安装入门图文教程!

按照下面的命令一行一行的敲入代码,语法我在这就不解释了~

真正从零开始,TensorFlow详细安装入门图文教程!

为了到达这一步,你可能付出了很多艰辛,可能中途出了很多错,但相信当你看到程序真的按照你的指令来运行了一遍,你会觉得这一切都是值得的。

真正从零开始,TensorFlow详细安装入门图文教程!

#彩蛋时间#

1.程序员们在接触一门新语言的时候,通常做的第一件事就是编写一个Hello World程序,这一惯例源自最初一批大神们对计算机程序的希冀,希望它们就像一个新生儿一样,能友善的对这个世界宣告它的到来。

2.数字42的含义非常深刻。据著名一本道科幻小说“银河系漫游指南”所说,42是一个关于“生命、宇宙以及一切”的问题的答案(哈?你问我问题是什么?)。谷歌的创始人很可能也是这本小说的狂热粉丝,因为谷歌把这个彩蛋也嵌入了它们的搜索引擎之中,而且谷歌的总部外面就有一个“42”的模型。

大型程序开发必备:IDE(集成开发环境)

虽然说在Terminal里就可以直接编程了,但我们总还是需要一个工具的,要不然要编一个大型程序几乎是不可能完成的事。这就是IDE出场的时候了。大家就会惊喜的发现,自己之前在C语言看过的熟悉的编程界面又回来了(当然它们很多都是收费的)。其实由于Python是开源的,理论上任何人足够厉害的人都能开发出针对它的IDE,而确实有很多人这样做了。牛人太多,他们做出的工具孰优孰劣大家并没有统一的意见,所以大家干脆就不介绍该用哪个了,这才造成了很多人对Python“抽象”的感觉。

好用的IDE有很多,本文介绍的是Komodo IDE的免费版Komodo Edit。在Linux下打开它的官网(点击链接http://komodoide.com/download/edit-linux64/#),下载得到的是一个压缩文件。点击右键解压。

Linux中安装有些第三方软件的方法和Windows不太一样,比如这款,在它的文件夹里有一个install.sh。

真正从零开始,TensorFlow详细安装入门图文教程!

这实际上就是安装文件,但直接打开它是不行的,要安装它还得在Terminal里进行。进入Terminal,确保自己在普通而不是Python环境下,然后通过输入cd+文件夹名称,逐层进入这个安装文件所在的文件夹,如进入Download文件夹,就输入:cd Download(Python对大小写敏感,因此最好养成在输入时都分清大小写的习惯。),因为在输入一个安装命令的时候,程序只会在你当前所在的那个文件夹(不包括子文件夹)里搜索安装文件的名称。习惯图形界面的人可能会有点头晕,但是只要牢记以下这点就能找到回家的路:打开Terminal时默认你所在的文件夹对应的文件管理器界面就是下图这个。在初期你可以一边开着图形界面打开文件夹,一边在Terminal里敲出对应的路径,这样就不会迷路了。

真正从零开始,TensorFlow详细安装入门图文教程!

当然,有些软件有更简单的安装方式,这里不讲了。

到达安装文件所在的界面之后,输入./+文件名称,如本例中就是输入./install.sh,效果如下:

真正从零开始,TensorFlow详细安装入门图文教程!

按照信息中给出的路径就可以找到启动这个程序的文件了,本例的文件在bin里。

真正从零开始,TensorFlow详细安装入门图文教程!

接下来的设置就和在Windows中差不多了。

真正从零开始,TensorFlow详细安装入门图文教程!

打开后,我们通过它试验一下官方教程中“介绍”部分给出的一个相对简单的算法。

点击New File

真正从零开始,TensorFlow详细安装入门图文教程!

点击右上角的语言选择,选择Python,这样就可以在输入过程中检查出一些语法错误。

真正从零开始,TensorFlow详细安装入门图文教程!

(如果直接复制的话,会把网页里带有的一些奇怪的代码也带过来,会导致程序运行出错,如下面示例中出现过的那样,因此需要将中文注释删掉。)将输入的代码保存为*.py,这是Python文件的后缀名。可以通过Terminal调用。按照之前的方法在Terminal中进入到存放文件的文件夹里,本文中的路径是这样的:

真正从零开始,TensorFlow详细安装入门图文教程!

然后输入Python+文件名,本例中是Python Text-3.py,由于这个算法很简单,很快就能得到结果。满满的成就感有没有?

真正从零开始,TensorFlow详细安装入门图文教程!

真正从零开始,TensorFlow详细安装入门图文教程!

总结

其实本教程只是开了一个很小很小的头,讲解了关于Tensorflow的一些最基础的知识,包括其他环境中的安装、GPU支持等稍微复杂一点的东西都没有讲到。但实际上这从0到1的过程却是难住很多人的最大因素。在了解到教程中的这些东西之后,相信理解Tensorflow的官方教程已经对你没有难度了,如果你跟着官方教程走下去,会发现其实这些东西并不算难,相信以各位的智慧一定能学会的。那么本次教程就到这里了,各位加油吧,说不定创造出下一个AlphaGo的就是你们呢。

题图来自Tensorflow官网

雷锋网原创文章,未经授权禁止转载。详情见转载须知

利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了 | 雷锋网

mikel阅读(1090)

如果上班的时候想放松一下,或者直说想偷偷懒,看点和工作无关的网页,这时候万一老板突然出现在背后,会不会感到很难堪呢?

来源: 利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了 | 雷锋网

如果上班的时候想放松一下,或者直说想偷偷懒,看点和工作无关的网页,这时候万一老板突然出现在背后,会不会感到很难堪呢?

有的浏览器设置了boss按键,手快的人还可以切换屏幕,不过总会显得不自然,而且经常搞的手忙脚乱的。

一个日本程序员决定自己动手,编写一个一劳永逸的办法,我们来看看他是怎么实现的吧~

思路很直接:用网络摄像头自动识别在工位通道走过的人脸,如果确认是老板的话,就用一张写满了代码的截图覆盖到整个屏幕上。

整个工程中应用了Keras深度学习框架来建立识别人脸的神经网络,和一个网络摄像头用来捕捉老板的人脸。

任务是这样的:

当老板接近我的工位时,电脑就会自动切换屏幕。

办公室的情况如下:

利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了

从老板的座位到我的座位大约6~7米,他会在离开座位后4到5秒钟到达我的座位,因此,需要在这之前隐藏屏幕,所以时间比较紧迫。

策略:

首先需要让电脑完成对老板面部的深度学习。然后在我的办公桌上摆上一个网络摄像头,让摄像头对着通道,当网络摄像头捕捉到老板的脸时就切换屏幕。

嗯,这是一个完美的项目。先取一个好名字,就叫Boss Sensor(老板探测器)好了。

利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了

Boss Sensor的简单结构图如下:

处理过程分为三步:

  • 网络摄像头实时拍摄图像
  • 学习模型检测和识别所拍摄图像的人脸
  • 如果识别结果是老板则切换屏幕

所需要的技术实现只有三项:

  • 拍摄人脸图像
  • 识别人脸图像
  • 切换屏幕

一步步完成之后整合就可以了。

拍摄人脸图像

首先找一个网络摄像头,我用的是BUFFALO BSW20KM11BK摄像头,大家随便找个清晰度够的就可以了。

利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了

最好不要用相机自带的识别软件裁剪人脸,因为后面的深度学习过程还需要处理。所以,我用Python和OpenCV编写了一段裁剪人脸图像的脚本,代码在这里下载。

偷拍到的人脸图像比我之前设想的更清楚▼

利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了

识别人脸图像

接下来,要用机器学习教会电脑识别老板的脸。

我们需要以下三个步骤:

  • 采集图像
  • 图像预处理
  • 建立机器学习模型

让我们一个接一个看一下。

采集图像

首先,需要收集大量的图片供电脑学习。一般来说有三种大量收集图片的方法:

谷歌图片搜索

Facebook的图像采集

从视频里截图

一开始,我像电影里的特工一样收集了各种搜索引擎上的老板照片,还有Facebook上老板自己上传的照片,但说实话,没有收集到足够的图像。所以,反正老板就在身边,我就简单粗暴的拍摄了一段他的视频,然后把视频分解成大量的图像。

图像预处理

现在我有很多人脸图像了,但还不能拿它们来建立学习模型,必须要裁剪掉与脸部不相关的部分。

我使用ImageMagick来提取人脸,你可以用别的图像软件来做。

总之,最后我收集了大量的人脸图像,就像这样: ▼

利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了

估计我是全世界拥有最多老板头像的人了,肯定比他爸爸妈妈要多的多。

现在可以准备机器学习了。

建立机器学习模型

Keras框架用来建立卷积神经网络和神经网络培训。Tensorflow用来写Keras的后端。如果只识别脸部的话,可以调用一些Web API比如微软的Computer Vision API,但这次我决定自己来实现,因为这个项目需要确保实时性。

网络体系结构大体如下,Keras非常方便,它可以很轻松的输出这样的结构: ▼

利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了

代码在这里下载。

至此,只要老板出现在摄像头中,我就可以识别出他来了。

切换屏幕

最后一步,很简单,学习模型识别出老板的脸之后,把电脑屏幕换掉就好了。

我是程序员,所以我准备了这样一张图:▼

利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了

电脑上只显示这张图片,这样就可以假装我在认真工作了。

这张图需要全屏显示,所以我调用了PyQt库,代码在这里下载。

一切工作都完成了。

成品

最后把分别实现的技术整合起来并验证,真的成功了!

“现在老板离开了座位,正走向我的工位。”▼

利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了

“OpenCV已经检测出人脸,将人脸图像发送给学习模型。”▼

利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了

“学习模型认出了他,屏幕自动切换。ヽ(‘ ∇‘ )ノ”▼

利用深度学习开发老板探测器,再也不担心刷着微博一回头突然看到老板了

这就是我的Boss Sensor,全部的源码都放在github上了,可以在这里下载。

总结

结合网络摄像头的实时图像采集和Keras深度学习框架,确实可以完成人脸识别

在实践过程中,我发现OpenCV的图像精度不够高,虽然不影响识别,但我准备改用Dlib来提高精度,另外我想自己编写人脸检测训练模型。

网络摄像头获取的图像不够清晰,我准备换个摄像头。

唉,坑还是越挖越深啊~

本文转载自公众号:51CTO   (ID:weixin51CTO )  作者@熊小妹。

机器学习并没有那么深奥,它很有趣(2)_36氪

mikel阅读(819)

通过“超级马里奥”游戏解读机器学习。

来源: 机器学习并没有那么深奥,它很有趣(2)_36氪

通过“超级马里奥”游戏解读机器学习。
机器学习并没有那么深奥,它很有趣(2)
编者按:在科技圈,如果你不懂“机器学习”,那你就 out 了。当别人在谈论机器学习娓娓道来时,你却一头雾水,怎么办?在跟同事的聊天中,你只能频频点头却插不上话,怎么办?让我们来做些改变!Adam Geitgey 撰写了一份简单易懂的《机器学习,乐趣无限》的资料,共分为5个部分,主要针对所有对“机器学习”感兴趣,却苦于不知从何下手的朋友,希望能借此让更多人认识了解“机器学习”,激发其对“机器学习”的兴趣。本文为第二篇。

第一篇:机器学习并没有那么深奥,它很有趣(1)

在这份指南的第一部分,我们讲到了,机器学习能够让你在不需要为具体问题专门编写代码的情况下,通过泛型算法告诉你一组数据的有趣之处,并且帮助解决你的实际问题。

这一次,我们将用其中一条泛型算法来做些非常酷的事情——让算法生成一个看起来像人工设计的游戏关卡。

首先,我们将建立一个神经网络系统;其次再给这个网络系统提供现存的“超级马里奥”游戏关卡数据;然后就可以坐等一个个新的游戏关卡诞生了!

机器学习并没有那么深奥,它很有趣(2)上面就是用我们的算法设计的一个游戏关卡。

就像在第一部分提到的,这份教程指南是针对所有对机器学习感兴趣,却不知从何下手的朋友。由于是面向大众,所以这份指南有概括性和不尽完整之处。但是我还是希望能借此激起大众对机器学习的兴趣,让更多人认识、了解机器学习。

作出更聪明、准确的猜测

回到指南的第一部分,我们创建了一个用于预估房子价格的简单算法 。所需提供的房子的相关数据信息如下表:

机器学习并没有那么深奥,它很有趣(2)

最后,我们得出了一个简单的预测函数:

机器学习并没有那么深奥,它很有趣(2)换句话来说,我们把上面信息表格中的每个属性数据与一个特定的权重相乘,然后把相乘的得数简单相加,从而得到了一个房子大概的预估价格。

与其看那些纷繁复杂的编码,不如用一个简单的图表来形象、直观地表示这个函数:

机器学习并没有那么深奥,它很有趣(2)

图中的箭头代表的是这个函数的权重。

然而这个算法只能解决那些输出结果与输入内容有着线性关系的简单问题,并不适用于其他复杂的问题。那么如果房价背后的现实因素并不像我们假设的那么简单呢?比如说,有可能邻近的周边环境对大面积及小面积住宅影响非常大,但是对中等面积的房屋基本没有影响。那么我们让我们的模型函数里涵盖所有诸如此类的复杂因素和细节呢?

一个聪明的做法是:把这些复杂的边缘情况中的数据一一用到算法中来测试其准确性。

机器学习并没有那么深奥,它很有趣(2)

我们可以先用四种不同的方法(即四种不同的权重数据)来解决这个问题。

那么接下来很自然地,我们就会得到四个不同的估价。把这四个估价合并为一个最终的价格预期,然后再次运用到我们前面使用的算法当中。

机器学习并没有那么深奥,它很有趣(2)

我们这个全新的“超级答案”是由前面四个不同的价格预估合并而来的。正是因为如此,与我们在单独的一个模型中所能涵盖的因素相比,它能模拟更多复杂的细节和案例。

什么是神经网络?

我们试着把前面四次不同的价格预估合并为一个大的图表:

机器学习并没有那么深奥,它很有趣(2)

看!这就是一个神经网络。每个节点都能够接收一系列数据输入,并应用不同的权重,并且能够计算出一个确切的输出值。把这些节点链接起来,我们就能模拟很多复杂的函数。

由于篇幅有限,我在这篇文章了省略了一些与之相关的内容,比如特征标准化和激活函数。但是最重要的部分是以下这些基本内容:

· 我们建立了一个简单的预估函数,它能接收一系列数据输入,然后把这些数据与各个节点的权重相乘,最后输出一个相对确切的预估值。这个简单的预估函数叫做神经元。

· 通过这些简单的神经元的链接结合,我们可以模拟那些对于单个神经元来说过于复杂的函数。

这其中的原理就像玩乐高积木。我们无法只用一个乐高积木来搭建不同的造型,但是我们如果有足够的乐高积木,我们就能用它们搭建各种各样的造型。

机器学习并没有那么深奥,它很有趣(2)

l  赋予我们的神经网络记忆的能力

我们以往了解的“类神经网络”是没有记忆的,当你输入一个相同的数据,它就只能返回到那个相同的答案。在编程计算中,这其实是一种无状态算法。

在很多案例中(比如房子价格预估),这种算法可能就足够解决你的问题。但是这种类型的模型函数是不能应对模式存在于时间推移中的数据的。

试着想象一下,我给你一个键盘,让你写一个故事。但是在你开始写之前,我要猜测你将在键盘上敲下的第一个字母,那么我究竟要猜哪个字母呢?

我可以用我的英语知识储备来增加我猜对的几率。比如,你可能会输入一个经常被用在故事开头的单词的第一个字母。如果我看过你曾经写的文章,我就能把范围缩小在你经常在故事开头使用的单词上。一旦我掌握了这些信息,我就能用它来建立一个神经网络,模拟计算你将以哪个字母开头的可能性。

我们这个神经网络的模型大概就像这样:

机器学习并没有那么深奥,它很有趣(2)

我们现在不妨把问题想得再复杂一点。假如说,停在你的故事的任意一个地方,我需要猜出你接下来要输入的下一个字母。那么这个问题就变得更加有意思了。

我们以海明威的《太阳依旧升起》这本书的开篇的几个单词为例:

机器学习并没有那么深奥,它很有趣(2)

能猜出在这个不完整的单词后面的第一个字母是什么吗?

你可能会猜“n”,因为这个单词很可能会是boxing。我们做出这个猜测,是基于对这个不完整的单词的判断以及我们最基础的英语单词的知识储备。同时句子中提到的“middleweight”(拳击比赛中中量级选手)也给了我们暗示,这个句子谈论的内容可能是拳击。

换句话来说,如果我们仔细考虑前面的字母顺序,并且结合我们的英语语言规则的知识,还是很容易就能猜出接下来即将键入的字母的。

因此,为了使用神经网络来解决这个问题,我们需要给我们的模型添加一种状态。我们每次使用这个神经网络来解决问题的时候,我们都会把中间计算结果自动保存下来,然后下次作为我们的部分输入再次使用。通过这种方式,我们的模型将会根据最近浏览的输入数据来调整预估结果。

机器学习并没有那么深奥,它很有趣(2)

时刻追踪这个模型的“状态”,你不仅有可能猜中故事中第一个字母,甚至有可能猜中在故事任意位置的下一个字母。

以上就是递归神经网络的基本内容,简单来说就是我们每使用一次这个网络,就对它自动更新一次,同时也根据它最近浏览的信息输入对预估结果进行更新。只要我们赋予了它足够大的记忆内存,它甚至能随着时间推移来模拟各种不同条件下的模式。

 猜测一个字母到底能有什么特殊意义呢?

猜测出一个故事中的即将输入的一个字母,这看起来很无聊也很无用吧?那么,猜测一个字母到底能有什么意义呢?

这其中一个很有代表性的意义就体现在手机输入键盘的输入内容自动预估功能。

机器学习并没有那么深奥,它很有趣(2)

看上面的图,接下来输入的字母最有可能是“t”。

接下来,我们试着把上面这种思路运用到一种极致。如果我们让这个模型不停地预估下面可能出现的单词,一直重复预估,会出现什么样的状况呢?那很可能这个模型就帮我们完成一篇完整的故事的创作了。

创作一篇故事作品

我们刚刚已经见识了猜测海明威小说中一个句子的下一个字母的方法和过程,那么接下来,我们不妨试着创作一个有海明威风格的完整的故事。

我们这里即将用到的是由Andrej Karpathy 编写的递归神经网络实现。Andrej Karpathy是一名来自斯坦福大学的深度学习研究人员,他曾经写了一篇非常优秀的关于运用递归神经网络进行创作的介绍,你能在github网站上找到所有关于这个模型的代码。

我们将根据海明威的《太阳依旧升起》这本书完整的内容来建造我们的预估模型。这篇作品中有362239个字词,共使用了84个特殊字符(其中包括了标点符号、大写字母和小写字母等等)。这些数据与我们在现实世界中的典型的应用量相比,实际上已经是非常小的了。为了建立一个更贴近海明威创作风格的模型,我们最好能掌握比这个数据多数倍的示例文本。但是这些数据作为展示递归神经网络创作过程的例子已经足够了。

在递归神经网络模型的测试训练之初,它还并不擅长字母预测。下面是在100次迭代训练后,我们的创作模型输出的内容:

机器学习并没有那么深奥,它很有趣(2)

你会发现,这个时候它已经能够预测出有时候单词之间需要以空格间隔开,但是这还不足够完成一篇文章。

在大约1000次迭代之后,这个模型输出的内容看起来总算有些像样了:

机器学习并没有那么深奥,它很有趣(2)

这个模型开始能够识别出一些句子的基本结构模式了,比如在句子末尾加句号,甚至能够给对话添加引号。有少部分的话语是通顺、可以理解的了,但是仍然有一大部分句子看起来是非常荒谬可笑的废话。

但是经过更多次的反复训练,这个模型的输出结果看起来已经相当不错了:

机器学习并没有那么深奥,它很有趣(2)

到现在为止,我们所使用的这个算法已经成功掌握了海明威的短小、直接对话的模式,所以它生成的一小部分句子在内容上还算是说得通的。

然后,我们把这个创作模型输出的内容与书中实际的原文做个比较:

把字词一一对照来看,我们的算法也已经做到了文章内容的再现,而且内容看起来还十分可信,使用的格式也非常恰当。这已经相当了不起了。

同样的,我们还不需要完全通过打草稿来创作文章了,我们可以给算法提供文章前面的几个字母作为种子文本,然后让算法根据种子文本自动输出接下来的一些字母。

不妨用这个自动输出的系统来玩玩。我们试着给我们脑中幻想的书制作一个假的封面,用“Er”“He”“The S”作为种子文本,创造一个新的作者名字和新的书名。

机器学习并没有那么深奥,它很有趣(2)

图:左边是真实的书,而右边是我们电脑生成的“无稽之谈”书。

至少看起来还不错!

但是最令人兴奋的地方是这个算法能够从任意的数据顺序中找出规律模式,这意味着它能轻易地生成看起来非常逼真的支票或者是假的奥巴马演讲稿。但是为什么仅被我们人类自己的语言所局限呢?我们可以把这个思路应用到任何一种有规律模式可循的顺序数据中。

在没有马里奥的情况下制作马里奥

2015年,任天堂为Wii U游戏系统推出了“超级马里奥制造”。

机器学习并没有那么深奥,它很有趣(2)

能自己设计游戏关卡,大概是所有孩子的梦想吧!

这个游戏让你在游戏板上随意设计出你属于自己的“超级马里奥兄弟”关卡,然后上传到网上让你的朋友们玩你设计的游戏关卡。在你专属的“超级马里奥”关卡中,可以包含原始游戏里的经典的特殊道具和敌人。这就像为玩着“超级马里奥兄弟”长大的人们而设计的一个虚拟乐高。

我们能用前面那个假的海明威风格作品的创作模型来设计一个假的“超级马里奥兄弟”关卡吗?试一试无妨!

首先,我们需要一些用于模型测试训练的数据。那么就先用1985年发布的“超级马里奥兄弟”游戏的室外关卡作为训练数据吧。

机器学习并没有那么深奥,它很有趣(2)

这真是最棒的圣诞节了!谢谢爸爸妈妈!

这个游戏总共有32个关卡,其中大约有70%都是室外游戏的风格,所以我们将选择室外的这一部分。

为了得到每个关卡的设计,我找到了游戏的原始版本,然后写了一个程序将关卡设计从游戏记忆储蓄里抽出。“超级马里奥兄弟”是一个有着30年历史的经典游戏,所以网上有很多可以帮你找到关卡设计是如何储存在游戏记忆中的的资源。从一个视频游戏的经典中调出关卡设计数据是一次非常有趣的编程经历,你一定要试试!

下面是这个游戏的第一关,如果玩过的话你可能还有印象的。

机器学习并没有那么深奥,它很有趣(2)

“超级马里奥兄弟”第一关

仔细观察,我们会发现这个关卡其实就是由一些简单的网状方块对象构成的:

机器学习并没有那么深奥,它很有趣(2)

我们还可以简单地把这些方块对象一一用字符顺序来表示,一个字符代表一个对象:

机器学习并没有那么深奥,它很有趣(2)

如上图,我们现在已经把关卡中的每个对象用一个对应的字符表示好了:

  • 空白格用“-”表示
  • 实心砌砖用“=”表示
  • 易碎砌砖用“#”表示
  • 金币砌砖用“?”表示

按照上面的思路,把关卡内的每个不同的对象用一个对应的字符表示。

最后,我们就会的到一个像下图这样的文本文字档:

机器学习并没有那么深奥,它很有趣(2)

一行一行地观察这个文字档,你会发现这个“马里奥”关卡好像确实没有一个固定的模式或者规律:

机器学习并没有那么深奥,它很有趣(2)

一行一行地看,确实是找不到一个相对固定的模式或规律。甚至有很多行是完全空白的。

只有当你以一种“系列栏状”的思维来看这个关卡文字档文本的时候,你才会发现其中的规律和模式:

机器学习并没有那么深奥,它很有趣(2)

一列一列地看,它确实是有一个相对固定的模式的,比如说:每列都是以“=”结尾的。

所以,为了让算法能顺利找到我们数据里的规律和模式,我们需要以列的方式输入数据。找出能最有效地表现你的数据的方式(也被称作“特征选择”),是使用机器学习算法的关键点之一。

为了训练这个模型,我们需要把这个文字档文本旋转90度,这是为了确保字符是按照一种更容易显示其规律和模式的顺序输入模型的:

机器学习并没有那么深奥,它很有趣(2)

模型训练

正如我们前面“海明威散文风格”创作模型的创作经验,一个模型在不断的训练和测试中才能一步步趋于完善。

我们的模型在初期阶段只经过少量的训练,还没有完善,所以输出的内容完全不像样:

机器学习并没有那么深奥,它很有趣(2)

虽然它已经有了“-”和“=”两个符号所搭建的大概框架,但是还没有找到关卡设计的规律和模式。

经过上千次的反复试验和训练,这个模型的输出结果开始有了不错的雏形:

机器学习并没有那么深奥,它很有趣(2)

这个模型已经找到了每行字符的长度应该相同的这个规律,它甚至还找到了“马里奥”游戏关卡的小部分设计逻辑和规律:在“马里奥”游戏中“管道”这个物件通常是两个砌砖的宽度,高度至少是两个砌砖,所以“P”这个字母(P代表“管道”)在文本文字档中一般是显示为2*2的群集。这个发现确实是相当酷的!

在经过更多次的训练以后,这个模型已经能根据关卡设计输出完全准确的对应字符数据了:

机器学习并没有那么深奥,它很有趣(2)

我们不妨用我们的模型来输出一整个关卡的字符数据,然后把它旋转回到水平状态:

机器学习并没有那么深奥,它很有趣(2)

大功告成!上面就是经由我们的模型输出的一整个游戏关卡。

这个字符数据看上去还不错!还有一些同样酷的事情值得关注:

  • 跟原版的“马里奥”游戏一样,在这个游戏关卡的开头,它就把“快乐云”(游戏角色,是一个漂浮在云上的小怪兽)设置在空中了。
  • 它能够知道管道是需要依附实心砌块才能浮在空中的。
  • 它能按照正常逻辑来设置敌人的位置。
  • 它不会设置任何会阻滞玩家前进的物件。
  • 它带来的游戏体验与真实的第一代“超级马里奥兄弟”游戏是一样的,因为它就是以原版游戏里现存的关卡为基础设计的。

最后,拿着我们的关卡设计,用“超级马里奥制作”软件把游戏重新制作出来:

机器学习并没有那么深奥,它很有趣(2)

上图就是我们的关卡数据在被输入至“超级马里奥制作”以后的结果。

机器学习并没有那么深奥,它很有趣(2)

游戏制作好了,自己先玩玩吧!

如果你有“超级马里奥制作”这个应用程序,你就可以先把这个游戏关卡用网络书签收藏起来再玩;你也可以通过搜索游戏编码“4AC9–0000–0157-F3C3”来玩这个关卡。

玩具vs 现实世界的应用程序

递归神经网络算法与现实世界的公司用于解决像语音探测、语言翻译等复杂的问题的算法是一样的。我们的模型之所以更像一个“玩具”,而不是非常高端的存在,是因为我们的模型是由非常有限的、少量的数据中训练的,在原版的“超级马里奥兄弟”游戏中没有足够多的关卡来为我们的模型提供足够多的数据。

如果我们能像Nintendo一样有成千上万个游戏玩家设计的“超级马里奥制作”的游戏关卡,我们一定也能建立一个相当完美的模型。然而现实是,我们没法像Nintendo一样拥有这么多游戏关卡数据的,因为那些大公司是绝不会免费透露他们的数据信息的。

因为机器学习在越来越多的领域都发挥着非常越来越重要的作用,所以区分一个程序的好坏的标准就将变成你用于模型测试和训练的数据量的多少了。这也就是为什么像谷歌和Facebook这样的大公司那么迫切地需要你的个人信息。

举个例子来说:谷歌最近开源了TensorFlow——一个用于建立大规模机器学习应用程序的软件工具包。谷歌这次将如此重要的、有能力的科技开源确实算是一个大举动,“谷歌翻译”等产品也是用这个框架实现的。

但是,如果没有谷歌在所有语言上庞大的数据支撑,你就不能与“谷歌翻译”相媲美的翻译软件。数据就是谷歌的高端所在。试想一下,下次当你打开“谷歌地图”里的历史位置记录或者是Facebook的历史位置记录时,你会发现它记录保存着你到过的所有地方。

深度阅读

在机器学习中,要解决一个问题通常没有一个标准的办法。在决定如何预先加工你的数据,或者决定使用哪个算法时,你会有无限的选择。通常来说,把各种不同的方法结合起来使用的结果比单个使用一种方法要好得多。

以下是一些读者发给我的链接,是关于设计“超级马里奥”关卡的一些其他有趣的方法的:

Amy K. Hoover的团队用的方法能够一一表示游戏关卡中的每一种物件对象(管道、地面、平台等等),就像在一整个交响乐中单独表示每一种乐器的声音一样。使用一种被称作“功能性搭建”的进程,系统能够用任何给定的对象类型的砌块自动增加关卡数量,比如说:你可以先草拟一个游戏关卡的基本框架,然后系统就能通过增加管道和障碍砌块来完善你的设计。

Steve Dahlskog的团队像我们展示了,如果按照一系列n-gram单词来建立游戏关卡数据的竖列模型,将更可能用比一个复杂的递归神经网络更简单的算法来输出游戏关卡。

注:本文由「图普科技」编译,您可以关注微信公众号tuputech,获得最新、最好的人工智能资讯。

机器学习并没有那么深奥,它还很有趣(1)_36氪

mikel阅读(834)

从0 到 1,机器学习入门指南。

来源: 机器学习并没有那么深奥,它还很有趣(1)_36氪

从0 到 1,机器学习入门指南。
机器学习并没有那么深奥,它还很有趣(1)
编者按:在科技圈,如果你不懂“机器学习”,那你就 out 了。当别人在谈论机器学习娓娓道来时,你却一头雾水,怎么办?在跟同事的聊天中,你只能频频点头却插不上话,怎么办?让我们来做些改变!Adam Geitgey 撰写了一份简单易懂的《机器学习,乐趣无限》的资料,共分为5个部分,主要针对所有对“机器学习”感兴趣,却苦于不知从何下手的朋友,希望。能借此让更多人认识了解“机器学习”,激发其对“机器学习”的兴趣。

相信很多人都已经厌倦了维基百科上的长篇累牍,迫切地希望能有人给出个更准确、更高水平的解释。这些,正是“机器学习”将为你做到的!

什么是“机器学习”?

机器学习,意味着你不再需要编写那些纷繁复杂的特定传统代码,机器运用一套通用的算法——泛型算法,就能告诉你关于一组数据的有趣之处。不需要写代码、编程序,只要把数据交给泛型算法,它就能自动建立起数据逻辑。

举个例子:用于分类的泛型算法是能够把一组数据分门别类的,用于识别手写数字的分类泛型算法同样能够做到在不改变代码的条件下将垃圾邮件和非垃圾邮件区分开。两者使用的是同一种泛型算法,但是因为输入的数据不同,所以输出的分类逻辑是不一样的。

机器学习并没有那么深奥,它还很有趣(1)

这一种机器学习算法相当于一个黑盒子,能够处理各种有关分类的问题。

“机器学习”是一个呈伞状结构的体系,除了分类算法以外,还覆盖了各种各样其他的泛型算法。

两类机器学习算法

你可以把机器学习算法暂且想象为拥有着两大类分支的体系——有监督学习和无监督学习。这两者的区别显而易见,不外乎是有无监督之差,但是其重要性却是不容忽视的。

①     有监督学习

假设,你现在是房地产经纪人,你的业务持续增长,所以你必须雇一帮新的实习代理帮忙。然而当下的问题是:你只要随便一瞥就能知道一间房子大概的价值,但是你雇来的实习代理不行,他们不如你经验丰富,还做不到对房子进行相对准确的估价。

那么为了帮助你的实习代理(当然同时也是为了给你自己放假),你可以编写一个能够完成房产估价工作的应用程序,这个程序能够根据房子的大小、周边环境等条件找出相似的房子,然后进行价格预估。

因此,你需要记录下你所在城市三个月内房产交易的信息。针对每笔交易,你需要记录下一系列细节信息,比如:房间数目、房子大小、周边地区环境,等等,最重要的是要记录下交易的最终价格。

机器学习并没有那么深奥,它还很有趣(1)

以上就是我们收集到的数据,专业地称之为“训练数据”,我们希望通过这些数据建立一个程序,来帮助我们对我们所在区域的其他房子进行估价。当然,我们同时也希望能通过这些数据,对区域以外的其他房子进行价格预估。

这种模式就叫做“有监督学习”。

你从一开始就知道了每间房子的价格,换句话说,你已经知道了一个问题的答案,而且你能够原路返回,重新思考这个问题,从而建立起一个解决这个问题的思路和逻辑。

那么建立一个能预估房价的应用程序,你需要把关于每间房子的数据信息——“训练数据”——输入你的机器学习算法中,算法就会得出用于解决这些数据关系的一套数学公式。

这就有点像一份数学考试的答案纸被涂掉了所有的算术符号,就像下面这张图。

机器学习并没有那么深奥,它还很有趣(1)

天啊!老师答案纸上的算术符号不知道被哪个淘气的学生都涂掉了!这个时候你应该很难看出这次考试考的是什么数学问题,到底是加法还是减法?

所以要解决到底是加法还是减法的问题,你这时就需要对左边和右边的数字进行一些“计算加工”来弄清他们之间的关系了。

通过这种“有监督学习”,你可以让电脑帮你完成一系列的“计算加工”工作。当你弄清楚等式左右两边的数学关系以后,你就会知道用什么方法解决这个数学问题了,那么类似的问题也就迎刃而解啦!

②     无监督学习

我们再回到前面提到的房地产经纪人的例子。假如就连作为房地产经纪人的你,对每间房子的价格都不确定,那该怎么办?

如果你了解到的只有房子的大小、位置这些信息,那也没关系,用我接下来介绍的“无监督学习”你一样能有所作为。

机器学习并没有那么深奥,它还很有趣(1)

机器学习可以让你在没有掌握有决定性意义的数字信息(这里指的是房子的价格)的条件下也能有所作为。

这就有点儿像,有个人递给你一张纸,上面写着一串数字(这里指的是除了房价以外的其他数据信息)然后告诉你“我也不知道这一大串数字是什么意思,但是你应该能从中得出些隐含的信息,好好干,祝你好运!”

我们拿到这串数字数据能做些什么呢?对于一个新手来说,你可以用一个算法自动识别出你的数据内部的细分市场区隔。你可能就会发现邻近大学地区的一些买家倾向于购买房间多、面积小的房子,而在郊区的买家则比较青睐建筑面积大的,房间数量不需要多的(大概只需三个)房子。了解了不同客户的不同需求能够对你的市场推广工作起到很大的指导作用。

除此之外,你能做的还有就是自动识别出那些与其他不同的离群孤立的房子,可能那些孤立出来的房子都是高楼大厦,所以你可以有针对性地把销售主力集中在这个区域。

在这篇帖子接下来的部分,我们将会更多地关注在“有监督学习”上,但这并不代表“无监督学习”就是无用的。事实上,随着算法的不断完善,“无监督学习”变得越来越重要,因为它在数据没有被贴上正确答案标签的条件下同样能使用。

给学者们的附注:确实是有很多不同类型的机器学习的泛型算法,但是对于刚入门的新手来说,从这两类算法开始确实是一个不错的选择。

运用“机器学习”给房子进行估价确实很酷,但是这真的算是学习吗?

作为人类,你的大脑可以解决很多种突发状况,而且在没有明确的指示的情况下同样可以学会处理这些状况。如果你很长一段时间都在做房屋销售,那么你就会对房屋的正确估价、房屋的营销策略、房屋的潜在客户等产生本能的反应。而强大的人工智能调查的目的就是把产生这种本能反应的能力在电脑上复制下来。但是就现在来说,机器学习算法还没能达到那么高的水平,它暂时只适用于一些特定的、有限的问题。因此,在这种情况下,“学习”被定义为“根据示例数据得出相应的公式来解决特定的问题”可能更为恰当。但是很显然“机器运用根据示例数据得出的公式解决特定问题”这个定义不能作为个好名字,所以,我们干脆就直接称之为“机器学习”。

当然,可能在50年后人工智能已经强大到那种地步了,那么你一定会觉得我写的这篇帖子里有点奇怪。如果真是如此,请你放下这篇帖子,让你的机器人保姆给你做个三明治,尽情享受人工智能带来的便捷和舒适吧。

话不多说,我们试试编写那个房屋估价的程序吧!

我们到底怎么编写一个能够对房子进行估价的程序呢?往下读之前,请你先在自己的脑海里想想。

假设你现在对“机器学习”一无所知,你大概会写一些房屋估价相关的一些基本规律和规则吧?就像这样:

机器学习并没有那么深奥,它还很有趣(1)

如果你能耐下性子细细研究上面这些代码,说不定你会写出个像样的估价程序。但是,这个估价程序并不是完美的,当价格出现波动时,你的估价程序可能就不适用了。

如果电脑能够帮你输出一个相对准确的估价函数岂不是更好?只要这个函数输出的估价能跟原始数据中的价格相吻合,没有人会在乎这个函数到底是怎么来的。

机器学习并没有那么深奥,它还很有趣(1)

换种方式来理解这个问题:如果把房子的最终价格比作一碗汤,而汤中的食材就是“房间数目”、“房子大小面积”、“周边环境”这些必需的信息。如果你了解每种食材(房产估价的所需信息)分别对这锅汤(预估的价格)的影响程度,你应该就会有一个相对确切的“炖汤食材比例”,这个比例同样也能用来对房子进行估价。

你会发现,以上那些假设虽然不甚恰当,且略微不切实际,但是会把你的原先的复杂的函数简化到以下程度:

机器学习并没有那么深奥,它还很有趣(1)

留意一下以下加粗的几组数字:841231951398213, 1231.1231231, 2.3242341421, 以及201.23432095。这些就是我们用于权衡计算的指标数字,如果我们能计算出适用于所有房子的完美指标,那么程序就能预估房子的价格了。

计算出这个完美指标最笨的方法就像这样:

第一步:

把各个指标设置为1.0

机器学习并没有那么深奥,它还很有趣(1)

第二步:

运用所有你了解的房产价格信息来测试你的程序,检查你求得的函数输出的结果与实际房价的偏差。

机器学习并没有那么深奥,它还很有趣(1)

用你求得的函数来对每间房子进行价格预估。

比如说,假设第一间房子实际售价为250,000美元,但是你的函数输出的预估价为178,000美元,那么就这一间房子而言,程序价格预估的偏差就是72,000美元。

现在把你数据库里所有的每间房子价格偏差的平方值相加。

假如你数据库里有500个房屋成交信息,而通过测试这些交易信息得出的你的函数预估偏差总值达到了86,123,373美元,这数字就代表着你的函数当前的偏差总值。现在,把这个偏差总值除以500,得出每间房子预估偏差的平均值,把这个平均值暂且先称为函数的“成本费用”。如果你能通过对权衡指标的把玩从而把“成本费用”降低至零,那么你的程序就完美了。这就意味着,根据输入的数据信息,你的程序就能够相对准确地对房子价值进行预估。

第三步:

运用所有可能的指标组合重复第二步。找到能让你函数的“成本费用”最大程度地降至零的指标组合,那你的问题就解决了。

三个步骤很简单吧!现在来看看我们前面都做了些什么吧:首先,你拿到了一些数据信息,然后把它运用到三个非常简单的、通用的步骤,最后得到了一个能对你所在地区的房产进行价格预估的应用程序(函数)。

“机器学习”如此神通广大,Zillow(美国一家房地产估价网站)可要当心咯!

然而,下面的这些问题可能会给你带来些困扰。

1.      最近40年以来,像语言学、翻译学等许多不同领域的调查显示,这些用于煮出一锅“数据炖汤”(根据刚刚炖汤例子创出的新词)的通用算法比人类自己琢磨出的一套规则有用多了,就连最笨的机器学习工具都要比专家级别的人类强。

2.      你最后研究出来的那个函数对“房间的大小面积”或是“房间数目”一概不知,它只知道通过那些输入的已知数据来算出最正确的估价答案。

3.      很可能你完全不了解一组指标数据是怎么预估出房产价值的,也就是说你得到了一个你不完全了解其工作原理,只知道它能帮你预估房价的函数。

4.      想象一下,假如你刚刚研究出来的房产价值预估的函数输入的不是系数变量“房产面积”和“房间数目”,而是一大串数字,而这其中的每个数字都代表着用装在你车顶上的相机所拍下的照片的像素亮度值。那么这个时候,把输出的预估结果称作“房产价格”就似乎不太贴切了,称之“方向盘转向度”才更恰当。至此,你就已经研究出一个能让汽车自己掌握方向的函数了。很神奇吧?

前面第三步中提到的“运用所有可能的指标”是怎么回事呢?

当然,你不可能通过一个个地尝试完所有可能的指标来找出一个完美的组合,因为这要花费你一辈子的时间去尝试无穷无尽的数字。

为了克服这种低效率的尝试,数学家们已经研究出许多种更为简单有效的方法。下面是其中之一:

首先,根据上面提到的步骤二中的数据信息写一个简单的等式关系:

机器学习并没有那么深奥,它还很有趣(1)

这个就是你的“成本费用函数”

现在,试着用机器学习的数学术语把这个等式关系重写一次

机器学习并没有那么深奥,它还很有趣(1)

θ代表你当前的指标数,J(θ)代表在当前的指标数下你的成本费用。这个等式关系就代表着我们现在的价值预估函数与实际的偏差程度。

如果我们把这个成本费用函数加入所有可能的指标数据,用曲线图像表示出来,我们会得到一个像这样的曲线图:

机器学习并没有那么深奥,它还很有趣(1)

 我们的成本费用函数曲线图图像呈现一个碗状,纵坐标表示成本费用。这个图像中蓝色的最低点就是我们成本费用的最低值,意味着我们的函数偏差值最小。相反,最高点就是我们函数偏差值达到最大。所以,当我们找到能使这个图像达到最低点的指标值的时候,问题就解决了。

机器学习并没有那么深奥,它还很有趣(1)

因此,我们要不断地调整我们的指标值来接近图像的最低点,就像在走下山路。只要我们能在不断的调整中,一点点接近图像最低点,我们最终就能在不一个个尝试数字的情况下找到最合适的函数方程式。

如果你还记得微积分学的一些知识的话,你应该会记得如果你求出了函数的导数,就相当于知道了这个函数在各个点的切线斜率。换句话来说,就是知道了哪个方向角度能使我们在图像上呈下降趋势,我们可以借助这些知识来接近图像最低点。

如果我们能运用每个指标值求出了成本费用函数的部分导数,那么我们就能相应地减少每个指标的值,我们就能离“山脚”更进一步了,终究会达到最低点,找出那个最佳的指标值。(如果上面的做法都不奏效,别担心,继续往下读。)

上面的是为函数找出最佳指标值的方法之一的相对高级的总结,我们称之为“梯度下降法”。如果你对这些细节感兴趣的话,可以深入探究一下。

当你使用机器学习软件工具库去解决一个实际的问题,以上的工作你都不用担心。但是了解它实际工作流程也是很有必要。

机器学习还给你带来了哪些方便?

从专业的角度讲,前面提到的泛型算法三步走也被称作“多元线性回归”。我们尝试着研究出一个能适用于所有房屋数据信息的等式关系,然后用这个等式关系去对一间你完全没有见过的房子进行价值预估。能够用这个看似虚拟的等式关系来解决实实在在的问题确实很让人吃惊。

然而,我前面介绍的方法在一些简单的案例中能奏效,但它并不是万无一失的。原因之一就在于房价的非线性的特点,也就是说房价是没有特定规律可循的。

所幸的是我们有很多方法去克服房价的不确定性。还有很多其他的机器学习算法能够解决非线性数据,像类神经网络或是有核支持向量机等;而且还有很多针对复杂的线性问题使用的线性回归方法。总之,不论哪种方法都是以找出最佳指标值为目的的。

然而,和大多数人一样,我还是忽略了过度拟合的问题。我们在初期很容易就能找出一系列切合你原始房产数据库的指标值,但是这些指标值仅仅适用于你的原始数据,对于原始数据库之外的新的房产数据就不起作用了。针对这个问题,我们同样有方法去解决,比如说正则化处理,或者使用交叉验证数据集。懂得怎么处理这些问题正是掌握机器学习的关键。

换言之,尽管基础理念都很简单,但是你要真正掌握机器学习并且取得成效是需要一些技巧和经验的。所幸,这些技巧和经验,是每个开发人员都能够通过学习掌握的。

机器学习的神奇之处在哪?

一旦你见证了运用机器学习技术就能轻轻松松完成一件貌似非常难的任务(比如字迹识别),你就会明白只要有足够的数据信息,就能用机器学习解决很多复杂的问题。你只需简简单单地输入数据信息,等着电脑给你输出一个适用于你的数据的等式关系。

但你必须要清楚机器学习只能够解决数据问题,所以你要确保你输入的数据信息对解决问题是有帮助的。

比如说,假如你建立了一个房价预估模型,而这个模型的依据是房子内盆栽植物种类,显然这个预估模型是不可能预估出房产价值的。因为盆栽植物种类与这间房子的价格是没有任何关系的,所以电脑是没办法导出这两者之间的关系式的。

机器学习并没有那么深奥,它还很有趣(1)

你只能建立一个实际存在的关系模型。所以切记,如果一个专家都不能人工地用那个数据去解决问题,那么电脑同样也是不能的。不要说既然人类都能解决,那么要机器何用,我们应该关注在机器在解决问题上帮人类省下了多少时间。

怎样进一步了解机器学习?

在我看来,当前机器学习的最大问题就是它的使用仅局限于部分学术界和商业调研,普及度尚待提高;同时,由于缺少简单易懂的行内资料,一些希望对机器学习有进一步了解的外行人只能望而却步。不过,这些问题正一步步被人类解决。

由Andrew Ng在Coursera开设的免费机器学习课程是相当有价值的,我强烈推荐从这个课程开始了解机器学习。它对那些有计算机科学学位的人和有一点点起码的数学基础的人来说更易理解。

你可以下载安装SciKit-Learn,这是个涵盖所有标准算法的Python框架,你能用它对各种不同的机器学习算法进行把玩研究。

注:本文由「图普科技」编译,您可以关注微信公众号tuputech,获得最新、最好的人工智能资讯。

机器学习并没有那么深奥,它很有趣(3)_36氪

mikel阅读(1006)

通过编写一个能够识别小鸟图片的程序来认识深度学习和卷积神经网络。

来源: 机器学习并没有那么深奥,它很有趣(3)_36氪

通过编写一个能够识别小鸟图片的程序来认识深度学习和卷积神经网络。
机器学习并没有那么深奥,它很有趣(3)
编者按:在科技圈,如果你不懂“机器学习”,那你就 out 了。当别人在谈论机器学习娓娓道来时,你却一头雾水,怎么办?在跟同事的聊天中,你只能频频点头却插不上话,怎么办?让我们来做些改变!Adam Geitgey 撰写了一份简单易懂的《机器学习,乐趣无限》的资料,共分为5个部分,主要针对所有对“机器学习”感兴趣,却苦于不知从何下手的朋友,希望能借此让更多人认识了解“机器学习”,激发其对“机器学习”的兴趣。本文为第三篇。

第一篇:机器学习并没有那么深奥,它很有趣(1)

第二篇:机器学习并没有那么深奥,它很有趣(2)

是不是早就厌倦了在阅读完一大段相关资料之后,对深度学习依然是一头雾水的状态?那就来改变这种状态吧!

机器学习并没有那么深奥,它很有趣(3)

机器学习并没有那么深奥,它很有趣(3) 现在,谷歌能够仅根据你的描述,让你在自己的相册中轻松地找到你想要的那一张,甚至都不需要你手动给照片加上标签!这是怎么做到的呢?

在前面两个部分中我们都提到了,这份教程指南是针对所有对“机器学习”感兴趣,却不知从何下手的朋友。由于是面向大众,所以这份指南有概括性和不尽完整之处。但我们还是希望能借此激发大众对“机器学习”的兴趣,让更多人认识、了解“机器学习”。

要是你还没阅读过这份教程指南的前面两部分,赶紧去看看吧!

运用深度学习进行对象识别

机器学习并没有那么深奥,它很有趣(3)相信你一定看过上面这个非常有名的《xkcd》网络漫画。

漫画的创作就是基于这样一种理念——让任何一个三岁小孩都能认出照片中的小鸟;然而,如何让一台计算机识别出不同的物体,五十多年来却一直困扰着我们最优秀的计算机科学家。

在过去的几年时间里,我们终于找到了一个相当不错的方法来进行物体识别。这种方法是运用“深度卷积神经网络”的。这个词听起来像是出自William Gibson的科幻小说中的一串文字,晦涩难懂;但是如果我们把它一个个分解来看,就容易多了。

那么我们就正式开工吧!——编写一个能够识别小鸟图片的程序。

l  从简单的入手

在正式学习识别小鸟的图片之前,我们先来学习识别一个相对简单的对象——手写的数字“8”。

在这份指南的第二部分,我们已经学习了神经网络是如何通过把许多简单神经元链接起来处理复杂问题的。我们是创造了一个小的神经网络,这个网络能根据房间数量、占地面积以及房子所处位置和周边环境等条件来估算一间房子的价格。

机器学习并没有那么深奥,它很有趣(3)

同时我们知道,机器学习的原理其实就是把同一个泛型算法应用到不同的数据中去解决不同的问题,所以我们可以先对同一个神经网络进行修正和调整,让它能够识别所有手写文本。但是为了简化工作,我们先来尝试识别一个手写的数字“8”

只有当你拥有数据,尤其是大量的数据,机器学习才会充分发挥其作用。因此,为了开展我们的工作,我们需要很多很多手写的数字“8”。幸运的是,研究者们为了这一目的,已经建立了一个手写数字的MNIST数据集。MNIST数据集提供了60000张手写数字的图像,每一张的尺寸都是18*18,下面是数据集中部分手写数字“8”的图像:

机器学习并没有那么深奥,它很有趣(3)

MNIST数据集中的部分手写“8”

仔细想想,其实所有数据都只是数字而已。

我们在第二部分建立的神经网络仅仅接收了三个数字作为数据输入,例如“3”个房间,“2000”平方等等。但是现在我们想要用我们的神经网络进行图像处理,那么究竟如何将图像,而不光是数字,输入进神经网络呢?

答案其实相当简单。一个神经网络是接收数字作为数据输入的,对一台计算机来说,一个图像其实就是一个表示图片中每个像素深度的数字方阵:

机器学习并没有那么深奥,它很有趣(3)

机器学习并没有那么深奥,它很有趣(3)

为了把图像作为数据输入至我们的神经网络中,我们只要简单地把这个18*18的像素图看作是由324个数字组成的数字集。

机器学习并没有那么深奥,它很有趣(3)

为了加工处理这324个数字输入,我们只要把我们的神经网络扩大至能容纳324个节点输入就好了:

机器学习并没有那么深奥,它很有趣(3)

注意!我们的神经网络现在有了两个结果输出,而不是之前的一个结果了。第一个输出的结果将预测了这张图像是手写数字“8”的可能性;而第二个输出的结果将预测这张图像不是数字“8”的可能性。有了我们目标识别对象的单独输出结果以后,我们就能运用一个神经网络来将同类型的对象归类成组。

这一次,我们建立的神经网络比上一次的要大得多(这次的输入容纳量达到了324,而上一次的仅为3!),但是任何一台现代计算机都能在眨眼间处理有着上百节点的神经网络,甚至在你的手机上也能运作得很好。

那么剩下的工作就是用大量数字“8”的图像和非数字“8”的图像来训练这个神经网络,让它学会把两者区分。当我们输入了一个数字“8”的图像后,我们告诉它这个图像是数字“8”的可能性是100%,不是数字“8”的可能性是0%。对相反的图像也是同样的做法。

以下是我们部分的检测数据:

机器学习并没有那么深奥,它很有趣(3)

嗯……这真是很棒的检测数据!

在短短的几分钟之内,我们用一台笔记本电脑就能完成对这种神经网络的训练。训练完毕以后,我们就能拥有一个能够精确识别数字“8”手写图像的神经网络了。那么,接下来就能说:欢迎来到这个20世纪八十年代后期的图像识别的世界!

l  隧道视野

不得不说这真的非常巧妙,只要简简单单地把图像像素输入进一个神经网络,就能建立图像识别了。机器学习真神奇,对吧?

嗯,当然它也并不是那么简单的。

首先,好的方面是我们的数字“8”“识别器”确实能够很好地识别简单的图像,但前提是数字必须是处在图像的中间:

机器学习并没有那么深奥,它很有趣(3)

坏消息是:一旦图片里的手写数字不是正好位于图片的中央时,我们的识别器就完全搞砸了——即使是一点点的位置变化,也足以让我们的神经网络犯错。

机器学习并没有那么深奥,它很有趣(3)

这是因为我们的神经网络只看过了“8”在图片中央的训练数据,它完全不知道不在图片中央的“8”是什么样子的。所以,它只学会了一种模式——处于图片中央的“8”。

我们都知道,在应用环境下,我们的神经网络看到的数据并不可能都这么的有规可循,它们通常是复杂多变的。所以,我们需要想出一种办法,让我们的神经网络能够识别出不仅仅是在图片中央,而且是在图片任意位置的“8”。

穷举法#1:用一个滑动窗口搜索整张图片:

既然我们的小程序已经能很好地识别出处于图片中央的“8”了,那么我们能不能简单地,一个个部分地扫描整张图片,直到我们找到包含“8”的部分,或者整张图片都被扫描完呢?

机器学习并没有那么深奥,它很有趣(3)

机器学习并没有那么深奥,它很有趣(3)

这个方法叫做滑动窗口,是一个对这个问题的暴力解决方式。在某些特定的情况下,它的表现非常不错,但是它非常低效。如果用这种方法,我们就需要一次次地检测同样一张图片,以找出处于图片不同位置和不同大小的“8”。

当然,我们有更好的办法!

穷举法#2:更多的数据和更深的网络:

在前面章节,在训练我们的神经网络时,我们只给它看了“8”处于图片正中央的图片。那如果我们用更多样的数据(“8”处于不同的位置和大小)来训练它,那会怎么样呢?

事实上,我们不需要获取新的训练数据。我们只需要写一个简单的脚本,让它生成把不同大小的“8”放到图片的不同位置就可以了,如下图所示:

机器学习并没有那么深奥,它很有趣(3)

根据已有的训练图片创建出不同版本的训练图片,这样,我们就创造了“合成训练数据”。这是一个非常有用的办法!

通过这个办法,我们能够轻易地拥有源源不断的训练数据。数据越多,意味着我们的神经网络需要处理的问题就越难。但是没关系,这个问题我们可以通过扩大网络来解决,同时网络本身也能够从中掌握更多、更复杂的模式。

为了扩大我们的网络,我们只需要一层一层地堆积节点

机器学习并没有那么深奥,它很有趣(3)

我们把这个称为一个“深度神经网络”,因为相比较传统的神经网络,它有更多的层。

这种想法早在二十世纪六十年代末期就已经出现了,但是直至最近几年之前,因为训练这么大型的神经网络计算量太大,过于缓慢了,所以这个技术一直没有被广泛应用。然而,一旦我们研究出如何使用3D显卡(用于快速计算矩阵乘法),而不是使用普通的计算机处理器,那么使用这种大型神经网络的想法就会迅速变得实用、可行。事实上,利用与你用来玩“看守人”完全相同的NVIDIA公司的GeForce GTX 1080显卡,我们就能够以惊人的速度完成对神经网络的训练。

机器学习并没有那么深奥,它很有趣(3)

但是,尽管我们可以扩大我们的神经网络,而且可以用3D显卡快速地对其进行训练;我们仍然没有找到一个万全的解决办法。用我们的神经网络处理图像的时候我们需要考虑得更细致、周全。

试想一下,把处于图片顶部的“8”和处于图片底部的“8”当成是两个不同的对象,然后训练我们的网络去分别识别它们,这种做法是毫无实际意义的。

所以,我们应该要找出一种办法,让这个神经网络更加聪明,聪明到不需要我们额外的训练,它就能自己理解一个数字“8”无论被置于图片的任何方位都是同一个对象。幸运的是,确实是存在这样一种解决办法的。

l  卷积就是我们想要的答案:

作为人类,你能够非常感官地知道图片是有一个层次或概念的结构的。我们来看这张图片:

机器学习并没有那么深奥,它很有趣(3)

免费献上我儿子的照片

作为人类,你应该能

立刻分辨出这张照片的层次结构:

· 照片中的地面是由草和水泥覆盖的;

· 照片中有个小孩;

· 这个小孩坐在一只橡胶弹跳马上;

· 这个弹跳马在草坪上。

最重要的是,不论孩子处在什么表面之上,我们都能够识别出这个孩子。我们不需要仅仅因为“孩子”这个对象所有可能处在的、不同的平面,再费心去分别研究每个平面上“孩子”的“构造”。

但是现在,我们的神经网络还做不到这一点。它会将处在图片不同位置的数字“8”看作是完全不一样的对象,它还不能够理解在图片中移动一个对象的位置并不代表创造了另一个新的对象,这就意味着它需要根据每个对象可能所处的不同位置,重新分别研究出不同的识别方式。这种办法是不科学的。

我们需要给我们的神经网络传输“平移不变性”的观念,让它知道,不论出现在图片的什么位置,“8”就是“8”。

接下来,我们将使用到一种被称作“卷积”的处理方法来给我们的神经网络输出这种观念。“卷积”这一概念,一部分是受到计算机科学的启发,还有一部分是受生物学启发(有些疯狂地科学家用一个奇怪的探针戳猫的脑袋,希望研究出猫的大脑是如何进行图像处理的)。

l  “卷积”的工作过程

之前,我们把所有图像当做网格数字方阵输入至我们的神经网络中。这次不同,我们将利用“一个对象无论处在图片的什么位置都是同一个对象”这一观念干一些比之前更聪明的事情。

下面就是具体的操作步骤和流程——

步骤一:把图像分解成相互重叠的图像块

类似于我们的滑动窗口搜索。我们首先把一个滑动窗口放置于完整的原始图片上,然后把每一张输出结果按照一个个小瓷砖状的、独立图片的形式保存下来。

机器学习并没有那么深奥,它很有趣(3)

完成这个步骤以后,我们就成功将我们的原始图片转换成77个大小一致的小方块图片了

步骤二:把各个图片小方块分别输入至一个个小的神经网络

之前,我们是将一整个图像输入至一个大的神经网络来识别数字“8”的。这一步与之前的操作一样,但是我们会分别单独输入所有的小方块图片来进行识别。

机器学习并没有那么深奥,它很有趣(3)

重复这一操作77次,一次输入一个方块图片

但是,这里的操作有一个很大的不同:我们将对这个处理小方块图片的神经网络保持相同的权重。换句话说,我们会对每一个小的方块图片都以完全一样的方式进行操作和处理。如果在操作过程中,任何小方块出现了任何不同的效果,我们将会对这个方块进行标记。

步骤三:把每一个方块操作的输出结果都保存到一个新的数组

我们不希望丢失原始的图片方块的排列方式,因此,我们把每一个图片方块的处理结果都保存下来了,并且按照原始图片的安排将其排列成一个网格。就像这样:

机器学习并没有那么深奥,它很有趣(3)

简单来说,整个过程就是我们从一个大的图像入手,最后我们得到一个相对小的集合,这个集合记录着我们原始图片中最有趣的部分。

步骤四:降采样

步骤三的结果是一个显示出原始图片最有趣的部分的数组,但是这个数组相当大:

机器学习并没有那么深奥,它很有趣(3)

为了缩减这个数组的尺寸,我们需要用一个叫做“最大池化”的算法来缩减其样本。

暂时不管最大的数字,我们先看这个集合的每一个2*2的小方块:

机器学习并没有那么深奥,它很有趣(3)

这一步骤的原理是:如果我们在构成2*2方块的四个输入方块中的任何一个发现有趣部分,我们就只会单独保留这个有趣的部分。这样一来,我们就能在缩减这个数组的尺寸的同时,保留最重要的部分。

最后一步:做出预测

到现在为止,我们已经把一个巨大的图像缩减到了一个相对较小的数组了。

这个数组其实就是一堆数字,所以我们可以把这个小的数组作为训练数据,输入至另一个神经网络。这个最终的神经网络将决定这个图像是否相匹配。为了把这一步与“卷积”步骤区分开来,我们称之为“全连接网络”。

所以,从头至尾,我们的五个步骤的操作流水线就是这样的:

机器学习并没有那么深奥,它很有趣(3)

添加更多步骤

我们的图像处理流水线包含了一系列的步骤:“卷积”、“最大池化”,再到最后的一个“全连接网络”

在解决现实问题的时候,这些步骤可以根据你的需要多次组合和叠加。你能有两个、三个,甚至是十个卷积层,你能在任何你想要缩减你的数据(降采样)的地方进行最大池化。

基本原理就是从一张大的图像入手,然后一步一步地、不断地把它压缩,直到你最后只得到一个单独的输出结果。卷积步骤越多,你的网络就能够识别越复杂的图像特征。

举个例子。第一个卷积步骤是学习识别锋利边缘的;第二个卷积步骤就能运用其识别锋利边缘的知识来进一步识别鸟嘴;同样的,第三个卷积步骤就可以运用其识别鸟嘴的知识来识别一只完整的鸟,以此类推。

以下是一个更加具有现实意义的深度卷积网络(类似于你在科研论文上看到的网络图)

机器学习并没有那么深奥,它很有趣(3)

在这个案例中,他们以一个224*224像素的图片开始入手,重复操作卷积步骤和最大池化各两次,再操作卷积步骤三次,最大池化一次,最后输入两个全连接层。这个最终输出结果就是这个图片被分解成的1000种类型的其中一个。

l  建立一个正确的网络

那么你怎么知道究竟需要组合、重复哪些步骤来让你的图像分类器表现最好呢?

说实话,你需要做大量的实验和测试才能回答这个问题。你可能需要测试100个网络,才能找到你的待解决问题的最优结构和参数。机器学习是一门需要不断实验和试错的科学。

l  建立我们的“小鸟分类器”

现在我们终于了解了如何编写一个能够判断一幅图是否为小鸟的程序了

像往常一样,我们需要一些数据来开始我们的工作。这个免费的CIFAR10 数据库包含了六千张鸟的图片和52000张其他图片,但是为了得到更多的数据,我们同时添加了Caltech-UCSD -200–2011鸟类数据集中的12000张鸟的图片。

下图是从我们组合数据库中选出的部分鸟的图片

机器学习并没有那么深奥,它很有趣(3)

下面这张图则是52000张“非鸟”图片中的一部分:

机器学习并没有那么深奥,它很有趣(3)

这个数据集确实能够沿着我们的目标正常工作,但是72000张低分辨率的图像相对于现实世界的应用仍然是远远不够的。如果你想要取得“谷歌水平”的成绩,那么你需要数百万张高清大图。在机器学习中,拥有大量的数据几乎比拥有一个好的算法还要重要。现在你知道为什么谷歌会愿意向你提供无限量的照片储存空间了吧?他们想得到你的图片数据,大量大量的数据。

为了建立我们的分类器,我们将使用TFLearn。TFLearn是谷歌的TensorFlow深度学习框架(这个框架有简易的API)的一个封装程序。它能让我们仅需要写几行代码就能定义我们的卷积神经网络 。

以下就是用于定义和测试网络的代码:

机器学习并没有那么深奥,它很有趣(3)

机器学习并没有那么深奥,它很有趣(3)

机器学习并没有那么深奥,它很有趣(3)

如果你是用一个有足够显存的好显卡(例如Nvidia GeForce GTX 980 Ti显卡卡或者是更好的)来训练,那么你就能在一小时之内就可以完成训练。如果你用的是一个普通的中央处理器,那花费的时间可能就会长一点。

恭喜你!我们的程序现在可以识别小鸟的图像了!

l  网络测试检验

既然我们已经有了一个经过训练了的神经网络,我们就来用用它!下面就是一个简单的脚本,这个脚本以一个图像文件作为输入,并且可以判断图像是否为鸟。

但是为了检验我们的网络的有效性,我们需要用大量的图像对其进行测试。我之前创建的数据集中有15000张图像作为校验集,当我用这个网络运行这15000张图像的时候,它的预估正确率达到了95%。

95%正确率,这数字看起来还不错吧?但是,还是要看情况而定。

95%的精确度到底有多精确?

我们的网络的精确度是达到了95%的,但是“魔鬼总是隐藏在细节里”,这95%能有各种不同的意义。

举个例子来说,假如我们的训练数据图像中,5%是鸟,剩下的95%不是鸟,会发生什么情况呢?一个程序作出“非鸟”的预测是95%准确的,但是它同样是100%无用的,因为图像不是我们需要的。

我们更需要关注的是其中的数字,而不仅仅是整体的准确度。判断一个分类系统的好坏在于,我们需要更关注这个系统是如何失误的,而不仅仅是它失误次数的百分比值。

与其考虑我们的预测是正确还是错误,我们还是直接把它分解为四个独立的类别——

  • 第一,这里是我们的网络正确识别出的鸟的图片,我们把它称为“真正例”。

机器学习并没有那么深奥,它很有趣(3)

哇!我们的网络能成功识别出大量的不同类的鸟!

  • 第二,下图是我们的网络正确识别出的“非鸟”的图片,我们把这些称作“真反例”。

机器学习并没有那么深奥,它很有趣(3)

用了我们的检验数据集中的15000张图片后,下面是我们的预估在各个分类的统计次数:

机器学习并没有那么深奥,它很有趣(3)

为什么我们要把我们的预测结果分解成如此呢?因为不是所有的失误都是以相同的方式产生的,不同的失误有着不同的失误原因。

想象一下,假设我们正在编写一个程序,这个程序要从心脏磁共振图像中侦探出癌症。如果我们正在监测癌症,我们宁愿得到一个“假正例”结果,而不愿意得到一个“假反例”结果。“假反例”将是最糟糕的结果,就是程序告知一个人他们没有患癌症,但实际上他们患上了癌症。

与其仅关注总精确度,我们不如计算精确度和召回指标。精确度和召回指标能把我们完成情况的好坏清晰地展现给我们。

机器学习并没有那么深奥,它很有趣(3)

上面的图向我们反映了我们预测图像为“鸟”的正确率达到了97%!但是这同时也反映了我们在数据集中仅找到了真实的鸟的90%。换句话说就是,虽然我们可能没法找到每一只鸟,但是一旦找到一只鸟,我们就能相当确定那就是一只鸟!

这一步将通向哪里?

现在既然你已经知道了深度卷积网络的基本原理了,那你就能尝试TFLearn中的一些例子,然后跟不同的深度学习工程师联合放手去干啦。TFLearn还有内置数据集,因此你甚至不需要用你自己的图片。

现在你也已经了解了如何分枝以及如何学习机器学习的其他领域,那么接下来何不学习一下如何运用算法来训练计算机玩Atari游戏呢?

 

注:本文由「图普科技」编译,您可以关注微信公众号tuputech,获得最新、最好的人工智能资讯。

MySQL中trim()函数的用法 - 江南听雨 - 博客频道 - CSDN.NET

mikel阅读(1390)

来源: MySQL中trim()函数的用法 – 江南听雨 – 博客频道 – CSDN.NET

trim函数可以过滤指定的字符串:

完整格式:TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str)

简化格式:TRIM([remstr FROM] str)

返回字符串 str , 其中所有remstr前缀和/或后缀都已被删除。若分类符BOTH、LEADIN或TRAILING中没有一个是给定的,则假设为BOTH。remstr为可选项,在未指定情况下,可删除空格。

mySQL> SELECT TRIM(' bar ');

-> ‘bar’

mySQL> SELECT TRIM(LEADING ‘x’ FROM ‘xxxbarxxx’); –删除指定的首字符 x

-> ‘barxxx’

mySQL> SELECT TRIM(BOTH ‘x’ FROM ‘xxxbarxxx’); –删除指定的首尾字符 x

-> ‘bar’

mysql> SELECT TRIM(TRAILING ‘xyz’ FROM ‘barxxyz’); –删除指定的尾字符 x

-> ‘barx’

MySQL中的去除左空格函数:

LTRIM(str);

mysql> SELECT LTRIM(' barbar');

-> 'barbar'

mysql中的去除右空格函数:

RTRIM(str):

mysql> SELECT RTRIM('barbar ');

-> 'barbar'

ecshop ueditor1.3.6编辑器实现上传图片自动添加水印

mikel阅读(1064)

本身是没有为上传图片添加水印的功能,想要在上传的时候添加图片水印,也很简单。以 ueditor 1.2.6 为例,打开php目录下面的imageUp.php文件,查找“$info = $up->getFileInfo();”,在这句代码的下面加入以下代码:

 

然后保存,就可以了。不过要注意的是:$water_img = “watermark.png”;//水印文件(替这里换成你要的水印)。

/* 添加水印 start */
$water_img = “watermark.png”; //水印文件(替这里换成你要的水印)
$img_min_w = 350; //添加水印需要图片最小达到的宽度(px),小于这个宽度时则不添加水印
$img_min_h = 60; //添加水印需要图片最小达到的高度(px)
$new_img = $ori_img = $info[“url”];

$original = getimagesize($ori_img); //得到图片的信息,可以print_r($original)发现它就是一个数组
if($original[0]>$img_min_w&&$original[1]>$img_min_h){ //当图片宽度大于300px才添加水印
$watermark = getimagesize($water_img);

$s_original = imgCreateFrom($ori_img, $original[2]); //$original[2]是图片类型,其中1表示gif、2表示jpg、3表示png
$s_watermark = imgCreateFrom($water_img, $watermark[2]);

$posX = $original[0] – $watermark[0]-6; //X坐标(右下角)
$poxY = $original[1] – $watermark[1]-3; //Y坐标(右下角)

//打水印
imagecopy($s_original, $s_watermark, $posX, $poxY, 0, 0, $watermark[0], $watermark[1]);
imagejpeg($s_original, $new_img); //生成新的图片
}

//根据文件类型 创建一个新图象
function imgCreateFrom($img_src, $val){
switch($val){
case 1 : $img = imagecreatefromgif($img_src);
break;
case 2 : $img = imagecreatefromjpeg($img_src);
break;
case 3 : $img = imagecreatefrompng($img_src);
break;
}
return $img;
}
/* 添加水印 end */

ueditor编辑器上传图片添加水印_Mpower_新浪博客

mikel阅读(1281)

ueditor编辑器上传图片添加水印_Mpower_新浪博客,Mpower,

来源: ueditor编辑器上传图片添加水印_Mpower_新浪博客

   我开发网站差不多一年了,每天都会遇到非同寻常的难题,现在就说说我今天碰到的一个事情吧!

     开发网站的后台,我使用了百度ueditor编辑器,本以为是万无一失、至高无上的正确选择。其实我使用了插件就不想再去动插件里的程序代码,可偏偏就阴差阳错,策划那边来一个天方夜谭——使用编辑器上传的图片要添加水印。让人焦头烂额的事情就是这样发生了,因为ueditor编辑器是没有添加水印功能的。
      早上就开始在百度里遨游,看看php添加水印的函数,收集ueditor编辑器添加水印的代码,然后整合在一起,相关的操作如下:
1.打开ueditor目录下的php目录下的config.json 文件
1.1    在上传配置项添加下面代码:
     “iswatermark”: “true”,  
2.打开ueditor目录下的php目录下的action_upload.php文件,搜索代码:
2.1
      case ‘uploadimage’:
        $config = array(
            “pathFormat” => $CONFIG[‘imagePathFormat’],
            “maxSize” => $CONFIG[‘imageMaxSize’],
            “allowFiles” => $CONFIG[‘imageAllowFiles’]
        );
        $fieldName = $CONFIG[‘imageFieldName’];
        break;
在“break;”前添加:$watermark = $CONFIG[‘iswatermark’]; 这句话就可以读取配置文件的”iswatermark”值了。
2.2   继续在这个文件搜索代码:
$up = new Uploader($fieldName, $config, $base64);
把它改成:$up = new Uploader($fieldName, $config, $base64, $watermark);   这样就可以实例化Uploader类时带上$watermark变量。
3.这是最后一步,也是最重要的一步。打开ueditor目录下的php目录下的Uploader.class.php文件。
3.1  在这个类里面添加“   private $water; //是否添加水印(属性)   ”这句话。
3.2  把构造方法改成(public function __construct($fileField, $config, $type = “upload”, $watermark = false)。
3.3  在构造方法里面写上  ($this->water = $watermark; )这句话。
3.4  在upFile 方法内部后面添加以下代码:
       if( $this->water ){ 
            $this->watermark($this->filePath,$this->filePath);
        }
3.5   在这个类文件里添加以下方法,实现图片添加水印就靠它了。
【*
* 图片加水印
* $source  string  图片资源
* $target  string  添加水印后的名字
* $w_pos   int     水印位置安排(1-10)【1:左头顶;2:中间头顶;3:右头顶…值空:随机位置】
* $w_img   string  水印图片路径
* $w_text  string  显示的文字
* $w_font  int     字体大小
* $w_color string  字体颜色
*】
public function watermark($source, $target = ”, $w_pos = ”, $w_img = ”, $w_text = ‘www.aiyu.com’,$w_font = 10, $w_color = ‘#CC0000’) {
$this->w_img = ‘../watermark.png’;//水印图片
$this->w_pos = 9;
$this->w_minwidth = 400;//最少宽度
$this->w_minheight = 200;//最少高度
$this->w_quality = 80;//图像质量
$this->w_pct = 85;//透明度
 
$w_pos = $w_pos ? $w_pos : $this->w_pos;
$w_img = $w_img ? $w_img : $this->w_img;
if(!$this->check($source)) return false;
if(!$target) $target = $source;
$source_info = getimagesize($source);//图片信息
$source_w  = $source_info[0];//图片宽度
$source_h  = $source_info[1];//图片高度
if($source_w < $this->w_minwidth || $source_h < $this->w_minheight) return false;
switch($source_info[2]) { //图片类型
case 1 : //GIF格式
$source_img = imagecreatefromgif($source);
break;
case 2 : //JPG格式
$source_img = imagecreatefromjpeg($source);
break;
case 3 : //PNG格式
$source_img = imagecreatefrompng($source);
//imagealphablending($source_img,false); //关闭混色模式
   imagesavealpha($source_img,true); //设置标记以在保存 PNG 图像时保存完整的 alpha 通道信息(与单一透明色相反)
break;
default :
return false;
}
if(!empty($w_img) && file_exists($w_img)) { //水印图片有效
$ifwaterimage = 1; //标记
$water_info  = getimagesize($w_img);
$width    = $water_info[0];
$height    = $water_info[1];
switch($water_info[2]) {
case 1 :
$water_img = imagecreatefromgif($w_img);
break;
case 2 :
$water_img = imagecreatefromjpeg($w_img);
break;
case 3 :
$water_img = imagecreatefrompng($w_img);
imagealphablending($water_img,false);
           imagesavealpha($water_img,true);
break;
default :
return;
}
}else{
$ifwaterimage = 0;
$temp = imagettfbbox(ceil($w_font*2.5), 0, ‘../../texb.ttf’, $w_text); //imagettfbbox返回一个含有 8 个单元的数组表示了文本外框的四个角
$width = $temp[2] – $temp[6];
$height = $temp[3] – $temp[7];
unset($temp);
}
 
switch($w_pos) {
case 1:
$wx = 5;
$wy = 5;
break;
case 2:
$wx = ($source_w – $width) / 2;
$wy = 0;
break;
case 3:
$wx = $source_w – $width;
$wy = 0;
break;
case 4:
$wx = 0;
$wy = ($source_h – $height) / 2;
break;
case 5:
$wx = ($source_w – $width) / 2;
$wy = ($source_h – $height) / 2;
break;
case 6:
$wx = $source_w – $width;
$wy = ($source_h – $height) / 2;
break;
case 7:
$wx = 0;
$wy = $source_h – $height;
break;
case 8:
$wx = ($source_w – $width) / 2;
$wy = $source_h – $height;
break;
case 9:
$wx = $source_w – ($width+5);
$wy = $source_h – ($height+5);
break;
case 10:
$wx = rand(0,($source_w – $width));
$wy = rand(0,($source_h – $height));
break;       
default:
$wx = rand(0,($source_w – $width));
$wy = rand(0,($source_h – $height));
break;
}
 
if($ifwaterimage) {
if($water_info[2] == 3) {
imagecopy($source_img, $water_img, $wx, $wy, 0, 0, $width, $height);
}else{
imagecopymerge($source_img, $water_img, $wx, $wy, 0, 0, $width, $height, $this->w_pct);
}
}else{
if(!empty($w_color) && (strlen($w_color)==7)) {
$r = hexdec(substr($w_color,1,2));
$g = hexdec(substr($w_color,3,2));
$b = hexdec(substr($w_color,5));
}else{
return;
}
imagestring($source_img,$w_font,$wx,$wy,$w_text,imagecolorallocate($source_img,$r,$g,$b));
}
  
switch($source_info[2]) {
case 1 :
imagegif($source_img, $target); 
//GIF 格式将图像输出到浏览器或文件(欲输出的图像资源, 指定输出图像的文件名)
break;
case 2 :
imagejpeg($source_img, $target, $this->w_quality);
break;
case 3 :
imagepng($source_img, $target);
break;
default :
return;
}
 
if(isset($water_info)){
unset($water_info);
}
if(isset($water_img)) {
imagedestroy($water_img);
}
unset($source_info);
imagedestroy($source_img);
return true;
}
public function check($image){
return extension_loaded(‘gd’) && preg_match(“/\.(jpg|jpeg|gif|png)/i”, $image, $m) && file_exists($image) && function_exists(‘imagecreatefrom’.($m[1] == ‘jpg’ ? ‘jpeg’ : $m[1]));
}
4.别以为这就完事了,做程序员不但要聪明,而且还要 careful。上面的工作过程只是一个内核而已,水印图片才是主角咧。
4.1  把水印图片命名为watermark.png,把它存放在ueditor目录下。如果你觉得这样不好,那么你在步骤3.4时候就写你水印图片的路径,温馨提醒一下:ueditor目录下的php目录是当前目录。
现在我们就看看效果吧ueditor编辑器上传图片添加水印ueditor编辑器上传图片添加水印ueditor编辑器上传图片添加水印
ueditor编辑器上传图片添加水印

ECSHOP安装百度编辑UEditor教程 - ECshop商城二次开发博客 - 博客园

mikel阅读(1159)

来源: ECSHOP安装百度编辑UEditor教程 – ECshop商城二次开发博客 – 博客园

ECSHOP系统自带的编辑器大家用过都知道,难用不说,还不能批量上传图片。很多朋友都喜欢百度编辑器,因为百度编辑器功能强大,使用方便,而且不会生成太多多余代码。
网上有许多ECSHOP整合百度编辑器的教程,但大多都有一些问题。
ECSHOP模板屋提供一个比较完整的教程。

 

先看效果图:

 

1、到百度编辑器ueditor官网下载最新版,将文件夹改名为“ueditor”,上传到 /includes/ 目录下
(也可以下载制作好的ueditor1_4_3_3-utf8-php版) 点击下载

 

 

百度编辑器ueditor官方地址:http://ueditor.baidu.com/website/download.html

 

 

2、打开这两个文件,一个是商品编辑,一个是文章编辑
/admin/templates/goods_info.htm
/admin/templates/article_info.htm

 

查找代码:

{$FCKeditor}

 

替换成以下代码

复制代码
<script type="text/javascript" charset="utf-8" src="../includes/ueditor/ueditor.config.js"></script>
<script type="text/javascript" charset="utf-8" src="../includes/ueditor/ueditor.all.min.js"> </script>
<!--建议手动加在语言,避免在ie下有时因为加载语言失败导致编辑器加载失败-->
<!--这里加载的语言文件会覆盖你在配置项目里添加的语言类型,比如你在配置项目里配置的是英文,这里加载的中文,那最后就是中文-->
<script type="text/javascript" charset="utf-8" src="../includes/ueditor/lang/zh-cn/zh-cn.js"></script>
<style type="text/css">
.clear {
clear: both;
}
</style>
<textarea id="goods_desc" name="goods_desc" style="width:100%;height:500px;"> {$goods.goods_desc}</textarea>
<script type="text/javascript">
delete(Object.prototype.toJSONString);
UE.getEditor('goods_desc')
</script>
复制代码

 

两个文件都这样修改。

 

注意这行代码:

<textarea id="goods_desc" name="goods_desc" style="width:100%;height:500px;"> {$goods.goods_desc}</textarea>

width和height分别是指编辑器的大小,但是IE内核的浏览器,有可能不支持写成px,所以编辑器的大小可能有些不完美,这是跟CSS有关,这个可以自行解决。

 

 

这个时候,其实ECSHOP后台编辑器其实已经可以正常使用了

 

这个时候上传会发现,上传到网站的图片目录跟原来的不一样。

 

在上传的文件夹 ueditor 下找到文件 ueditor\php\config.json 文件打开

 

打开这个文件,按里面的说明修改你的上传文件路径。参考官方上传路径说明:http://fex-team.github.io/ueditor/#server-path

 

 

如果进入,商品列表、分类等等,出现报错,提示缺少Ajax,如图这样:

 

 

 

下面接着提供解决方法

 
第三步:解决后台js冲突

打开 /admin/templates/pageheader.htm
在头部找到代码:

{insert_scripts files="../js/transport.js,common.js,../js/utils.js"}

替换成代码:

<script type="text/javascript" src="../includes/ueditor/fix_jquery/jquery.min.js" rel="stylesheet" /></script>
<script type="text/javascript" src="../includes/ueditor/fix_jquery/jquery.json-1.3.js" rel="stylesheet" /></script>
<script type="text/javascript" src="js/common.js" rel="stylesheet" /></script>
<script type="text/javascript" src="../includes/ueditor/fix_jquery/transport_json.js" rel="stylesheet" /></script>
{insert_scripts files="../js/utils.js"}

 

——————————————华丽丽的分割线—————–