为什么Python是AI从业者的首选语言?

Phoenix Phoenix 2018.2.18 00:00 浏览(511) 评论 (0)

Python语言从1991年发布第一个版本,至今已经快30年了。作为一种解释型语言,很多年里一直打着“脚本语言”的标签,并因为运行速度被诟病。

但是现在,如果你想从事人工智能行业的技术工作,学习Python已然成为了必须。

根据数据平台 Kaggle发布的2017年机器学习及数据科学调查报告,在工具语言使用方面,Python是数据科学家和人工智能从业者使用最多的语言(见下图)。

IEEE综览(IEEE Spectrum)发布的2017最受欢迎编程语言列表中,Python同样位列第一(见下图)。

笔者并不是Python粉,做了十几年程序员,工作语言最开始是C,后来用Java,现在用C#。

却也不得不承认,在日常工作中,Python所占的比例越来越大了。

即使不是开发最终提供给用户的产品,做POC或Prototype会用到Python;处理数据会用到Python;验证论文也会用Python……

毋庸置疑,Python已经成为了AI从业者的首选。

曾经被认为是“学生才用”的Python,为什么顶尖的大公司都在用?为什么Python忽然之间变得这么招人爱?

究其原因,笔者认为,大概有以下几个:

 

I. Python是一种说人话的语言

解释一下,所谓“说人话”,是指这种语言:

  1. 开发者不需要关注底层

  2. 语法简单直观

  3. 表达形式一致

我们先来看几个代码的例子:

C 语言Hello World 代码:

int main()
{ 
   printf("Hello, World!");
   return 0;
}

Java 语言Hello World 代码:

public class HelloWorld {
    public static void main(String[] args){
        System.out.println("Hello World!");
    }
}

Python 语言Hello World代码:

print("Hello World!")

仅仅是一个Hello World程序,就能看出区别了,是不是?

编译 VS 解释

当然,仅仅是一个Hello World的话,C和Java的代码也多不了几行。

可是不要忘了,C和Java的代码要运行,都必须先经过编译的环节。

对于C语言来说,在不同的操作系统上使用什么样的编译器,也是一个需要斟酌的问题。一旦代码被copy到新的机器,运行环境和之前不同,还需要重新编译,而那台机器上有没有编译器还是一个问题,安装上编译器后,也许和之前最初的编译器有所区别,还得修改源代码来满足编译环境的需求……

我到底做错了什么?我只是想运行一个别人写的程序而已[泪目]

而Python则不用编译,直接运行。而且都可以不用写文件,一条条语句可以直接作为命令行运行。不要太方便咯。


我们来看一个实际一点的例子:创建一个链表,把0-9逐次插入到链表中。再从head开始逐一打印链表中每个节点的值。

这样一个程序,看看用C,Java和Python分别如何实现:

【创建打印链表 - C代码】:

struct list_struct
{
    int val;
    struct list_struct *next;
};

struct list_struct* create_list(int val)
{ 
    struct list_struct *head = NULL;   
    struct list_struct *ptr = (struct list_struct*)malloc(sizeof(struct list_struct));
    if(NULL == ptr)
    {
        printf("\n Node creation failed \n");
        return NULL;
    }
    ptr->val = val;
    ptr->next = NULL;
    head = ptr;
    return head;
}

struct list_struct* add_to_list(list_struct* curr, int val)
{    
    if(curr = NULL)
    {
        printf("\n Node insertion failed \n");
        return NULL;
    }
    struct list_struct *ptr = (struct list_struct*)malloc(sizeof(struct list_struct));
    if(NULL == ptr)
    {
        printf("\n Node creation failed \n");
        return NULL;
    }
    ptr->val = val;
    ptr->next = NULL;
    curr->next = prt;
    return ptr;
}

void print_list(list_struct* head)
{
    struct list_struct *ptr = head;
    while(ptr != NULL)
    {
        printf("\n [%d] \n",ptr->val);
        ptr = ptr->next;
    }
    return;
}

int delete_list(list_struct* head)
{
    struct list_struct *curr = head;
    struct list_strcut *del = NULL;
    if(head== NULL)
    {
        return -1;
    }
    else
    {
        while(curr->next != NULL)
        {
            del = curr;
            curr = curr->next;
            free(del);
        }
        free(curr);
    }
    return 0;
}

int main(void)
{
    int i = 0, ret = 0;
    struct list_struct *head = create_list(0);
    struct list_struct *prt = head;
    for(i = 1; i<10; i++)
        prt = add_to_list(prt,i);
    print_list(head); 
    delete_list(head);
    return 0;
}

【创建打印链表 - Java代码】:

public static void Main(String[] args)
{
    List<Integer> numbers = new ArrayList<Integer>();
    for (int i = 0; i < 10; i++) 
    {
        numbers.add(i);
    }
    for (Integer num : numbers) {
        System.out.println(num);
    }
    return;
}

【创建打印链表 - Python代码】:

numbers = list(range(10))
print(numbers)

这个时候是不是已经看出区别来了?

底层细节

请注意C代码中的malloc()free()函数。它们在干嘛?它们在操作内存。

malloc()为链表的单元申请一块内存,free()释放掉它。如果申请了的内存空间没有被释放掉,就会产生著名的内存泄漏。

允许开发者(程序员)直接掌控底层细节,是C的闪光点,是有相应需求程序的利器,是其高性能的保障。但对于不需要也没有兴趣成为“语言大师”的用户,几乎就是灾难。

Java和Python都有自动垃圾回收机制,能够自动管理内存。再也不用手动分配和回收内存空间了!

变量类型

Java和Python都是诞生在上世纪90年代初期,有许多相似之处。但也有很多不同。

Java是静态类型语言,一个变量一旦被指定了一个类型,就不再接受其他类型的值。

例如上面例子中的 List<Integer> numbers = new ArrayList<Integer>(); numbers既然已经被声明为每个element都是Integer类型,就不能接受其他(例如String)类型的值。

动态类型语言Python就不受这个限制。下面的代码一样可以运行:

numbers = list(range(10))
numbers.append('test')
print(numbers)

打印结果是:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'test']

当然,静态类型 vs 动态类型各有其适用域,并不是说动态就一定比静态好。

不过,写AI相关的程序时,处理大量非结构化数据是必然要求。针对这一场景,动态类型自有其可以施展的地方。

语言语法

和Python比,Java的语法更“啰嗦”。

从上面的例子已经可以看出,创建一个链表,Java还需要声明和逐个插入节点,而Python则可一行代码完成从链表创建到插入节点及赋值的全部操作。

这还只是一个例子。在真正的使用中就会发现,对于很多非常简单基础的操作,Java非让你很别扭地写好几行,Python直接一句搞定。

这样的结果就是,Python写起来省事,读起来也方便。可读性远超Java。

表达风格

在10年或者更久远之前,Python经常被用来和Perl相提并论。毕竟在那个时候,C是系统级语言,Java是面向对象语言,而Python & Perl则是脚本语言的双子星。

Python和Perl在设计层面有一个非常大的区别:

  • Python力求让不同的人在撰写同样功能实现的代码时,所用的表达形式尽量一致;

  • 而Perl则是故意追求表达的千姿百态,让同一个人在不同地方写同样功能时所用具体形式都不同。

从哲学层面讲,Perl的追求更加自由主义,更利于释放人类的多样化天性。也确实有很多Geek范儿程序员因为这一点推崇毫无限制的Perl,鄙视到处设限的Python。

然而,Perl写的程序——那叫一个乱七八糟!

当你想遇到问题,想在网上找点实例代码看看的时候,搜到的Perl example千姿百态,很难找到一种“大众”的解法。而不同写法之间,还很难保证相容。

这个问题其实在Python vs Java上也有,只不过程度要低得多。

Java语言本身并没有想要把自己变成书写代码诗歌的载体。但是因为它长年大量地被应用在企业级软件的后台开发,夹杂进了太多并非语言本身却又与其使用不可分割的东西,进一步加剧了Java的繁杂。

如果不是想成为代码诗人,或者语言大师,只是想用尽量简单直接的方法,把事情做了,首选语言确实是Python。

 

II. 强大的AI支持库

由于Python语言自身所具备的特性,使得它成了做数据处理、机器学习和深度学习的人们的首选。

毕竟这些领域早期的主体是研究人员和数据科学家。他们并不是职业程序员,编程语言本身与他们而言仅仅是一种工具。

他们没有兴趣搞什么“XXX是最好的编程语言”,也不想陷入语言类型、特征的争论,仅仅是需要一种能够在付出最小学习代价的前提下,尽快将他们的想法实现为代码的载体。

如此一来,Python就成了他们的掌中宝。作为回报,他们向Python反哺了大量用于数据处理和机器学习的支持库。

其中最著名的NumPy和sklearn(scikit-learn),它们是现在每一个有志于入行AI的人都不可能忽略的。

矩阵运算

NumPy由数据科学家Travis Oliphant创作,支持维度数组与矩阵运算。结合Python内置的math和random库,堪称AI数据神器!有了它们,就可以放心大胆玩矩阵了!

大家知道,不管是Machine Learning,还是Deep Learning,模型、算法、网络结构都可以用现成的,但数据是要自己负责I/O并传递给算法的。

而各种算法,实际上处理的都是矩阵和向量。

使用NumPy,矩阵的转置、求逆、求和、叉乘、点乘……都可以轻松地用一行代码搞定,行、列可以轻易抽取,矩阵分解也不过是几行代码的问题。

而且,NumPy在实现层对矩阵运算做了大量的并行化处理,通过数学运算的精巧,而不是让用户自己写多线程程序,来提升程序效率。

有了Python这种:语法简洁明了、风格统一;不需要关注底层实现;连矩阵元素都可以像在纸上写公式一样;写完公式还能自动计算出结果的编程语言,开发者就可以把工作重心放在模型和算法上了。

ML模型

用Python实现大多数经典模型,几十上百行代码就够了。

当然,对于普通用户,也可以连算法都不用管,只是调用Scikit-Learn的接口就可以了。

比如,训练和使用一个logistic Regression模型,只需要下面几行代码就可以了:

# import the LogisticRegression  
from sklearn.linear_model import LogisticRegression   

# Use default parameters
classifier = LogisticRegression()  
# train model
classifier.fit(train_set, target)  
# do test
y_hat = classifier.predict(test_set)  
# print out test results
print y_hat

支持图表

Python还有许多图标方面的支持库。用来生成dashboard上的各种图形表格,是非常简单的事情。

比如使用Plotly图形库,下面这些炫彩的图形,就随便用啦:

 

III. 规模效应

语言简单易学,支持库丰富强大,这两大支柱从早期就奠定了Python的江湖地位。

不过当然咯,罗马不是一天建成的,凡事都需要积累。虽然NumPy的前身在1995年就出现了,不过正式的NumPy却是到了2006年才发布。sklearn则发布于2007年。

根据以高收入国家Stack Overflow问题阅读量为基础的主要编程语言趋势统计,可以看出,近年来,Python已然力压Java和Javascript,成为目前发达国家增长最快的编程语言(见下图)。

由图可见,2012年之后,对于Python相关问题的浏览量迅速增长,从时间上看,这一趋势正好和近几年人工智能的发展重合。

技术的普及推广就像滚雪球,早期的积累相对缓慢,一旦过了临界点,就是大爆发。

别的不说,就说现在tensorflow,caffe之类的深度学习框架,主体都是用Python来实现,提供的原生接口也是Python。

如今,Python在AI领域的老大地位已经奠定。

从现在开始学AI,舍Python其谁?

本文链接 https://www.mangoxo.com/blog/yM5jjb5j 版权所有,转载请保留地址链接,感谢!

Phoenix 关注
來一遭,做一事。 等一人,愛一次。
  • 964 动态
  • 1,986 相册
  • 97 粉丝
  • 3,033 获赞