这段时间重新学习了web前端的技术栈,其实一开始加入社团时就是从前端开始入门的,等到了会仿写几个页面后就跳到了后端的坑,从html、css、js(只学了一点)又马不停蹄的转到.net平台、后来在老司机的带领下我们放弃了不开放的.net平台投入了python的怀抱

python的确很好,“内裤”很多,相对于.net 相对于封闭的生态圈, python对第三方的类库的依赖很大,pip 是程序的常客,看到一个好的类库就pip下来了。

学了不少程序语言,从静态语言到动态语言,这其中的转变刚开始的确让人很苦闷。

自己从c系的语言过来,刚接触C的时候对于“过程编程”有很深的体会,结果并不重要,重要的是过程,有时候为了写好一个完美的函数自己苦思冥想好几天,花在一个函数上的时间比项目的时间都多。

然而到了学习python, 自己把C系的学习习惯带到python , 在做项目的过程中,当自己写完一个函数的时候总在想怎么优化代码,怎么抽象化对象让事情简单,慢慢的走入一个误区,让我忘记了python的口号 life is short, I use python .

python是一门目的性很强的语言, 先让我实现功能,其他以后再说, 我以前使用的时候对过程强调的太多了, 一个函数我得测试测试很多遍,确定每个参数的作用还有影响, 花了太多时间, 适得其反,我的代码一点都不 pythonic

我在学习 python的过程中走了很多误区,总结起来有几点:

  • 太注重过程,不注重结果
  • 太注重功能丰富,不注重简单

在我看来, pythonic 就是用最简短清晰的代码最快的完成自己的目的

python和javascript

这个都是动态的脚本语言,javascript更倾向于脚本

两个家伙在我看来都是鸭式语言, 当然js更倾向函数式,而python更倾向于对象式.

python 是目的性强, javascrip 是表现力强

以前在后端的时候总觉得只要把自己那端的语言学好就行了, 任何事python都能用来解决, 无论是数据库还是服务器,就算是图像都能用python处理(使用PIL),虽然有着GIL,有这性能低下等等的问题 .
颇有一番”学好数理化走遍全天下都不怕”的念头,

然而在实际项目中慢慢发现, 计算我能用几百行python代码画出一朵花来,用js几句话就在canvas上弄出来了,而且很轻松就能换成其他的东西.

得益于node.js社区的火热, 现在javascript也能在后端大显身手了, 学习了一点node.js,感觉通过node.js对js的封装,让javascript变成了一门类python的语言, 原本js文件只能运行在浏览器里面,通过node.js将每个文件封装成模块,就像python将每个文件封装成package,通过模块与模块的合作,js也能像python那样简单的用几行代码就构成一个强壮的服务器(虽然说现在node.js有点不稳定,但是随着node社区的努力也能将node.js强壮起来)

总结

通过一个星期的重温js, 自己简单的涉猎了现在很火的Angular,Ionic.和Node.js,并简单的搭建 Electron + Cordova + Ionic + Angular 原来博客 的 Desktop端
(linux + windows + OS)的软件版,还有移动版(由于本人没有OS操作系统,只做了Android版),还花了半天时间搭建了这个基于hexo的博客,算是完成了全平台的搭建

接下来我会自己工作前的大学时光好好的培养自己解决问题的能力,希望能在工作前爱上并享受自己将要做的工作!

最近从python2转到python3,发现还是有一些不同,一些库改名字很好解决,但是这个import机制不了解原理是不好理解的.

python2是默认相对路径导入,python3是默认绝对路径导入

首先这个包的导入机制,就是你在一个module里面引用另一个module,python运行文件有两种方式,一种是直接以主文件运行(默认以这种方式运行,同下面一种有点区别),一种是以module形式运行,就是用python -m filename方式调用.

以module的方式运行

####### 什么是相对导入和绝对导入呢
相对导入是用一个.来声明的,相当于Unix上的选择当前文件夹.

假设你的文件目录为下面的

main
|    main.py
|     __init__py
|   momod+
|      | __init__.py
|      | pack.py
|       | flask
|      |    |  __init__.py
|       |    |  myflask.py
--------------------
python里面的module分三种,一种是build-in module(内建库),一种是第三方库,还有一种是你自己写的库(如上面的flask).

在python2里面,当你import 一个module时,搜索的顺序是 内建库,自己的库,第三方库.

####### 而在python3里面顺序为 内建库,第三方库,你自己的库.

我自己感觉python3的import的机制更为清晰,因为当你import一个库时,假如你写的库和第三方库重合时,你优先导入第三方库,如果你不适用声明相对导入的话,你无法正确的导入自己的库,而使用.来声明库来自自己的代码让代码的结构更加清晰了.所以如果你想让你的代码兼容py2和py3,你自己的库都要采用相对导入方法来导入.
比如在momod 里面的pack.py假如想引用flask的myflask.py要这样写

from .flask import myflask

########### 假如你在py2中写了 from flask import myflask(并且你安装了flask库),这个是可以成功运行但是在py3中就会报错,因为他会优先导入flask库假如你没有显示声明相对导入的话.


上面成立的前提是将pack.py以module方式运行,或者运行main.py在其中引入pack.py.接下来讲讲以主文件运行的不同.

当你直接使用

python pack.py

你假如在pack.py里面使用了这个

from .flask import myflask

引用了自己的myflaskmodule,在py2和py3中都会下面报这个错

SystemError: Parent module '' not loaded, cannot perform relative import

因为当你以主文件方式运行 pack.py ,python会吧pack.py重命名为__main__,所以用.相对路径也不会是当前文件.所以全部都只能用绝对引用.所以在主文件运行在python3里面有个问题,假如你自己的库与第三方库有重名.

python3默认绝对路径,自己的库不会优先于第三方库被扫描.有两个解决方法,把自己的库重命名,第二个方法就是把包含主文件的文件夹加上init.py,你可以在sys.path的路径里加上..或者具体上一个上一个文件夹的路径.怪绕口的,其实你只要python能找到你的上一个文件夹,就行.

说到这里顺便插一句对doctest和集成测试的理解.

由于我平时喜欢一边写代码一遍测试功能,图方便就使用doctest直接插在方法里面,在代码后面加上

if __name__ == '__main__':
        import doctest
        doctest.tesmod()

平时写小module的时候没有问题,在将python2转python3时候,出现问题,因为我要测试这个module时,会报上面的那个错,因为我要测试他的话必须将它作为主文件.查了资料知道,其实doctest虽然在当前页面代码测试,但是对于module的话,最好采用集成测试,一是module很多,假如一个一个运行很麻烦,二是有时候module必须多个一起测试,所以测试module时要用集成测试来取代doctest.

###

最近学了两个python库,一个负责管理线程,一个负责管理进程,原来一直写的都
是些单线程的程序,虽然web也关于并发和多涉及到线程,但都是框架管理的,学习>过后发现了解线程和进程对python的web开发也有一定帮助。下面先谈谈这对python对线程和进程的支持再谈谈对这两个库的应用。

python对线程的支持并不是非常好,所以你可以在很多文章上批评python的多线程的弊端,但是为什么python对多线程支持不好呢,为什么其他语言比如

静态语言没有这个弊端呢。

首先我们要知道python是一种解释性语言,每段代码都需要解释器编译运行,解释器有很多种最主要的是CPython,其他还有IronPythonJython,官方的是CPython解释器,我们一般说对多线程支持不好的就是说的CPython解释器(用的人最多就省略成python解释器),python解释器为什么对多线程支持不好呢,是因为GIL的存在,当然这个存在就是因为这门语言的的特性产生的。

GIL是什么呢,下面是官方的解释

In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

就是GIL是python的互斥锁,简单的理解就是代码会锁住python解释器。理解代码的锁定是什么必须要先了解什么是多线程

多线程表示一个主线程,多个子线程,主线程是程序执行时系统自动给你申请的一个线程,而子线程我们可以理解为一个代码块,我们可以充分利用硬件的支持比如说多核,让一个CPU执行主线程,其他CPU执行子线程,通过操作系统的虚拟内存技术让所有线程共享相同代码空间达到提高代码效率的作用,我们可以通俗的把一个进程比作一辆火车,车厢头为主线程,每节车厢为子线程,只要你车厢(子线程)越多,你运的货物也越多,但是也要考虑硬件的方面,

了解完多线程是什么我们就可以解释GIL对多核CPU工作性能的影响了,在单核CPU里面,主线程在释放GIL的时候,把CPU让给子线程,子线程代码块得到GIL,然后执行,这样就能充分利用CPU,这个GIL对单核性能的发挥没有影响,能得到100%的利用,但是在多核的的时候就有问题了,假如主线程的代码一直需要解释器来执行,
比如说下面

GIL.acquire()
try:
    while True:
        do_something()
finally:
    GIL.release()

主线程代码对GIL的锁定和解开只间隔很小的一个系统时间,子线程在其他CPU核心得到GIL解开后CPU的调度命令后才能被唤醒,但是当唤醒后,主线程的代码又锁了GIL,然后只能等待主线程下次调度命令,但是到了切换时间又切换回去到待调整状态,一直处于唤醒,等待的恶性循环,多核的功能完全没有发挥出来而且还比单核更加差,所以python因为GIL的存在对密集型的线程支持不佳,但是假如主线程是在执行想web这样等待用户输入,而不是每分每秒都在使用解释器执行代码,多线程的优势就能发挥出来。

解决方案

GIL作为解释器的一个Bug一样的存在,我们也有一定的解决方法,开线程,和用Ctype绕过解释器是我们一般的解决方法,你想了解更多可以看这个
接下来主要解绍用multiprocessing来绕过多线程的瓶颈

线程锁和进程锁

为了实现线程安全,我们也要借助锁的存在,我们先用下面的代码来验证一下多线程对于线程安全的问题。我们声明一个线程锁 threading.Lock(),
class Counter(object):
    def __init__(self, start=0):
    self.lock = threading.Lock()
    self.value = start

def increment(self):
    logging.debug('Waiting for lock')

    self.lock.acquire()
    try:
        if self.value < 8:

模拟负载

            logging.debug('Acquired lock')
            self.value = self.value + 1

    finally:
        self.lock.release()
def worker(c):
    for i in range(2):
        pause = random.random()
        logging.debug('Sleeping %0.02f', pause)
        time.sleep(pause)
        c.increment()
    logging.debug('Done')
counter = Counter()
for i in range(20):
    t = threading.Thread(target=worker,args=(counter,))
    t.start()
main_thread = threading.currentThread()
for t in threading.enumerate():
    if t is not main_thread:

保护线程

得到value值

我们运行之后得到counter.value值为8,这很好理解因为我们限制了它的大小小于8时才自增1,但是如果我们把锁去掉呢,我们把self.lock.acquire()``self.lock.release()都注释掉,得到的结果却是一个21,而且每次运行的结果都可能不一样,由于线程在实现自增的时候有一定的时间(time.sleep(2)),所以当多个进程执行的时候当他们从堆栈上取到counter.value值都为7时,这时候他们都满足
counter.value小于8,所以都执行了自增,在系统负载2秒之间(time.sleep(2))有多少个线程执行就会逃过我们给他的限制,这样就造成了线程的不安全,但是我们给他加上锁之后,无论开多少个线程,最终结果都是8。在python里面我们线程锁和进程锁我们可以看做是同一种东西。

ps:当同一线程相互争夺锁时,失败的会进出线程队列等待锁解开。

线程进程工作方式

单行

单行主要通过锁来实现,线程通过锁threading.Lock()对象创造锁,进程通过multiprocessing.Lock()对象创建进程锁,单行操作一般都是对共享数据修改的一种保护。

并行

并行操作是一般是对数据的一种共享,一般不对公共数据涉及修改,我们可以创造很多线程和进程一起并行操作,也可以限制线程和进程的并行数量,两种方式选择主要是判断代码类型是I/O密集还是线程密集型的。如何限制并行数量我们可以通过threading.Semaphore(sizenum)(进程为multiprocessing.Semaphore(sizenum))我们可以控制对共享的线程数量。进程提供了一个进程池的类型(multiprocessing.Pool),我们可以创建一个维护了一定程的进程池,但是他同时并行的数量并没有控制,只是帮我们创建了这个进程池,每个进程并不是只执行一个任务,可能执行多个方法通过一个进程.

单行混合并行

单行和并行混合我们可以通过在代码中设置锁来实现,当然python给我们提供了两种对象来实现单行和并行的控制,线程的是threading.Event()threading.Condition(),进程的是multiprocessing.Event()multiprocessing.Condition() 两种对象都是提供了一种命令指令,但是Event对象可以用来判断命令是否下达而做出相应的反应,而Condition对象更倾向于当命令下达后才执行并行的操作。

线程和进程通信方式

当我们想让线程和进程共同执行一些固定的任务,我们就需要线程和进程之间能够通信,线程和进程通信我们使用队列(Queue),进程和线程的Queue有点差异,就是进程Queue传递的对象必须pickle化,而且为了能够使用join()(保护进程)task_done(通知任务完成),我们一般使用JoinableQueue
代替Queue在进程中。

Queue对象之间通过putget通信,我们把任务put上去,Queue自动分配给当前的线程或进程,
这样就能实现对任务的流水作业话。

引用

12/26/2015 10:50:21 PM GIL维基资料

GIL博文

申请了一个阿里的15体验的云服务器,同自己玩的虚拟机还是有点不同的。

1.用户名和密码

找了半天没有找到那个是用户名,试了实例的id,没有用,最后终于在登录帮助名里面找到了,用户名竟然是root!!!!,我用的是Ubuntu系统,说好的Ubuntu不提供root权限的呢,阿里还真会改造Linux系统
,但是我觉得用root登录还是不安全,我觉得新建一个用户吧

在root权限下

useradd -s /bin/bash -r -m yourname

解释一下,本来直接useradd yourname 就可以新建一个yourname账号,但是如果用你新建的用户登录的话,你无法使用Tab键和上下左右键 ,你键入 echo $SHELL,会发现是/bin/sh,因为Ubuntu默认创建账号使用/bin/sh,假如你没加这个可以删掉 用这个userdel yourname重新来一遍,搞完这个只是创建了一个普通用户,你使用不了sudo获取最高权限,这个怎么办,很简单在/etc/sudoers里面找到
root ALL=(ALL:ALL) ALL

模仿它加上自己的账号名就可以了。

学了鸟哥的书前面基础后,突然想在Linux下用gcc玩C语言,然后了解到了Vim这个神一样的编译器,接下来经过超长时间虐心的安装无数插件无数依赖包,突然有种打自己一顿的感觉,还好终于把Vim装的和VS差不多了,接下来我介绍我安装Vim的经验吧。

我虚拟机下的Linux原来是红旗6的,但是我改了一下yum的包源成CentOS的并且全部update一下后就神奇的变成了CentOS6,虽然他们两个是同一家公司,但是总给我一种由盗版成了正版的感觉。。

闲话不多说,刚开始装第一个插件是Ctags

刚开始装的时候我是在X-Windows里面的这里下载再转回shell敲

$ tar -xzvf ctags-5.6.tar.gz
$ cd ctags-5.6
$ make

make install

后来我发现不用这么复杂直接在X-Window下面复制到Terminal里面就可以了,毕竟后面安装的代码都是十几行,根本扛不住。。。。

装完三个感觉整个我太苦逼,简直是辛苦啊,不是说好的敲几下键盘就可以吗。
后来了解到linux有几个软件可以帮忙安装而且解决依赖性,比如ubuntu的apt-get,redhat的rmp,yum,但是问题来了,我的黄狗(yum:yellow dog)怎么没用啊,全都装不上,一查错误提示,原来我没用被授权,原来RedHat更新软件是要收钱的,但是CentOS不用,然后我就用了CentOS的源,当时我就想只想装个git,然后就没用然后了。终于全部更新完了,yum也可以用了,用yum果然爽多了,直接

yum install git    

git就装好了。如果想知道怎么改源,点击这里


好了装好了源接下来装软件就敲一敲代码就行,不用去网上找包下载再安装。

装好一些热门的插件后,我碰到了第一个最难装的插件YouCompleteMe(YCM),装完之后感觉就是神器一般的存在,但是装完之前一直在感慨,我去怎么没个卵用啊,而且装llvm(安装YCM必须先安装的软件)时,我用编译安装方法因为一些库的缺失一直报错,后面采用二进制安装方法安装完llvm才成功按上YCM。
推荐新手采用二进制安装方法安装llvm,想知道怎么安装YCM这些点击这里

安上一些实用的插件后,最后安装调试神器gdb,有三种方式使vim可以调试程序(与gdb一起工作),

vimgdb,pyclewn,clewn,三个我都试了,第一个要编译一下vim,我失败了,第二个要用python2.4+支持,我python2.6然并卵,每次都说不支持python2,第三个是用c写的,终于成功,安装非常简单,
点击这里了解详情.
装完了,我终于可以使用clewn打开gdb和gvim,然并卵,我写的程序并不能在gdb里面运行,一直说无法识别。。。。。。搜了一下原来是编译的时候的问题,用gcc编译的程序要带上-g参数才能在gdb里面用(我还以为我clewn没装好)
例如

gcc -g test.c -o test

加上-g参数就行了。终于我的vim可以用了。。。。。。

最近在学习大数据,书看了不少,但是总是觉得很迷茫,不知道怎么学下去,今天
突然想写点什么来
总结一下这些天.

起因

逛博客的时候看到一篇分享如何修炼成大数据高手感觉很有趣

买了两本书

大数据时代

失控

这两本书都是很多年前写的,但是最近这几年随着”大数据”被大家越炒越热,随即被大家所看重.

这两个作者很牛,在30年前大数据还只是萌芽的时候就提出未来大数据的重要性和价值.

大数据是什么了,现在为什么这么火,以前没有大数据吗?

大数据的产生就像是科技带来的附带品一样,原来我们把信息存贮在图书馆里面,因为人类的活动产生的信息越来越多,图书馆也越来越大,但是由于管理和存贮的成本越来越多,我们被迫要缩减浓缩我们的信息,我们想出了很多很方法来对付这种情况,比如抽样,只要抽取一部分的代表信息存在图书馆里面然后记录主要特征和平均分量,我们就可以把信息降低几个数量级.

但是现在不同.

芯片做的越来越小,容量做的越来越大,我们有能力存贮所以的信息,一些先驱发现我们用另一种思维去对待信息.

用全体数据而不是随机样本

用混杂性而不是精确性

用相关关系而不是因果性


string

原来的很多函数都逐渐迁移到strunicode对象上去了,
不过有两个函数没有迁移出去


第一个是capwords

个人觉得没什么卵用
就是将英文单词首字母大写

比如

string.capwords('this are some words')

输出为 This Are Some Words


第二个我觉得挺有趣,他可以帮你把对应的文字换成你设定的

我们可以用它来设计出莫斯密码’=’.

"""create a table"""
table = string.maketrans('abc','123')
print 'abc123'.translate(table)

输出为123123成功把abc转成了123


string还有一个模板类型Template
这个类型同我们转义差不多(%),不过能够实现的
更加自主化
我们可以继承这个类来修改模板类的具体实现
而且这个模板类有一个


textwrap

由于sublime输出一个很长的字符串很卡,这个格式化字符串的类能够帮我们
解决很多问题

我一般去除整体缩进然后去填充字符串

dedented_text = textwrap.dedent('...a long word...')
print textwrap.fill(dedented_text, width=50)


由于网站要实现图片和文字的混排的上传
所以在网上找了富文本编辑器的插件,发现CKEditor这款还不错的插件

我用的是4.5.1这个版本,的确很好用,只是引用了一个js文件就可以实现。


  1. 将网上下的CKEditor包解压放在根目录下
  2. 在页面上引用CKEditor的核心包ckeditor.js
<script src="ckeditor/ckeditor.js" type="text/javascript"></script>;
  1. 在页面添加一个输入框textarea

    <textarea name="individual" id="individual" runat="server"></textarea>
    <script type="text/javascript">
     CKEDITOR.replace('individual');
     </script>
    

只要通过上面上面几个步骤就能实现富文本编辑器,但是点开图片上传功能,发现只有上传url的功能,并不能本地上传图片,百度了一下发现由于安全性问题CKEditor没有上传功能,只有安上CKFinder才能实现上传功能,于是我在官网下了ckfinder__aspnet_2.5.0.1,同CKEditor一样引用JS文件(只要引用ckfinder.js)

<script src="ckfinder/ckfinder.js" type="text/javascript"></script>
  • 由于我是MVC的网站基于.net4.5,在官方给的包里面有一个asp.net网站实例放在_source文件夹里面,里面有一个基于.net2的示例网站,一运行就报找不到 System.Web.UI.Design这个命名空间的错,所以我把它从项目中排除,把项目中bin中debug文件夹下的CKFinder.dll复制出来,引用到我自己的项目中。

    接下来要配置CKEditor来让CKFinder引用进来,在CKEditor文件夹下config.js在CKEDITOR.editorConfig = function (config) {};方法中添加如下代码:

    config.filebrowserImageBrowseUrl = ‘ckfinder/ckfinder.html?Type=Images’;
    config.filebrowserFlashBrowseUrl = ‘ckfinder/ckfinder.html?Type=Flash’;
    config.filebrowserUploadUrl = 'ckfinder/core/connector/aspx/connector.aspx?command=QuickUpload&type=Files';
    
    config.filebrowserImageUploadUrl = ‘ckfinder/core/connector/aspx/connector.aspx?command=QuickUpload&type=Images’;
    config.filebrowserFlashUploadUrl = ‘ckfinder/core/connector/aspx/connector.aspx?command=QuickUpload&type=Flash’;
    config.filebrowserWindowWidth = ‘800’; //“浏览服务器”弹出框的size设置
    config.filebrowserWindowHeight = ‘500’;

注意在配置Url的时候要修改成相对于网站本地网站磁盘文件路径,比如说,你的网址是http://example.com.cn ,你把ckfinder文件夹放在Admin下的Editor文件夹,那么所有url要改成下面类似的格式

config.filebrowserImageBrowseUrl ='/Admin/Editor/ckfinder/ckfinder.html?Type=Images';

否则会报404错误,

最后一步是修改一个函数让所有人能看到服务器上传文件夹里面的文件,在ckfinder文件夹下面的cofig.ascx文件,找到 CheckAuthentication函数将返回值改成true

当然如果你想修改上传文件的地址,你可以在上面方法里面找到SetConfig()方法,找到BaseUrl,修改为你想上传的地址,

—–

PS:

我是在在VS里面进行调试的,由于VS的IIS在调试的时候不允许对磁盘文件的路由地址访问,就是CKFinder通过ckfinder.html这个html来实现上传图片的功能,但是这个在调试的时候VS无法访问这个文件,所以一直报404错误,可以修改IIS来允许IIS访问磁盘文件,步骤如下:

  1. 右键点击IIS Express,选择显示所有应用程序
  2. 找到运行网站的配置,进入applicationhost.config文件夹
  3. ctrl+f 寻找UrlRoutingModule
  4. 将preCodition设置为空字符

    <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
    

如果你是用MVC进行表单传值的话,你必须在post方法上面添加 [ValidateInput(false)] 属性,如果不这样的话就会报下面的错

“/”应用程序中的服务器错误。
从客户端(content="<p>sdfsdafwewo shdfh...")中检测到有潜在危险的 Request.Form 值。

最近在学利用python进行数据分析,发现pandas这个库对数据的处理非常灵活,
而且号称python的maltlab的.其在图形绘制也非常方便

在Windows下安装python关于科学计算的库非常不方便,还好有一些公司做好了关于python计算库在Windows安装的安装文件,这里我推荐anaconda,我推荐安装32位包,因为64位有很多库不支持.

pandas内部是使用numpy做存贮结构的,所以我们必须先了解一下numpy

先谈谈我对机器学习的理解

什么是机器学习?

我们人类有从婴儿开始就开始学习,父母教我们穿衣吃饭、老师教我们读书写字,我们开始能辨别好人坏人,开始通过自己的经验来判断新事物。

机器学习很简单,就像人一样,我们教机器通过我们教的来判断新的事物,或者在从新的事物里面学习处理新的事物。

这看起来很复杂的样子,但是从我们神经网络来看,我们可以把学习当做建立一个神经元连接,通过输入的信号得到一个输出的信号.我们只要简单的把输入的信号分类就可以了.通过无数个分类我们就可以建立复杂的神经系统,进而实现’学习’这个功能.

如何分类?

涉及到分类,假如输入的信号种类只要两种,我们就可以简单用if-else来实现分类功能,但是有时候输入信号种类个个都有细微的差别,只是遵循某种规律,这时候我们不能用简单的if-else来进行分类了,下面我就按照书的顺序来解释各种强大的分类方法.

K-近邻算法 ( k-Nearest Neighbor )

作为本书的第一个机器学习算法,K-NN算是我感觉原理最简单的一个了.

假设我们有两个点, 红点为(-1, -1)分为红类, 绿点为(1, 1)分为绿类
图片1

接下来我一个点(0, -1),这个点应该分为红还是绿呢,我们添加两条辅助线

蓝点离红点距离为1,蓝点离绿点距离为2.2,我们很轻松的可以知道这个点应该分为红类.
现在我们进一步推广,当有很多种类点的时候,当我们二维扩展到N维,给一个点a我们只要选取距离a最近的K个种类,我们就基本能判断他属于这K个种类的,这就是K-近邻的原理了.

K-近邻算法是最简单最有效的算法了,但是他也有缺点,比如他必须保存所有训练样本的数据,当训练样本很大的时候就会占用很多内存空间,我们后面会学到的KVM只取支持向量的训练样本来计算可以减少很多占用内存

而且K-近邻算法对训练数据集都要计算距离值,实际使用可能会非常耗时,我们后面学到的logistic回归能很好解决这个问题.

######### 总而言之,KNN作为小样本时非常简单粗暴,但是他无法给出任何数据的基本结构信息.接下来我们要学习用概率测量解决分类问题,这个算法能解决这个问题

(决策树)[]