阅读编程资料时经常会看到API这个名词,网上各种高大上的解释估计放倒了一批初学者。初学者看到下面这一段话可能就有点头痛了。
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。——百度百科
以C语言为例,我们使用fopen()函数可以打开一个文件,感觉非常简单。文件保存在硬盘上,要经过复杂的处理才能显示,这些细节对我们来说是透明的,由操作系统完成。也就是说,我们调用fopen()函数来通知操作系统,让操作系统打开一个文件。
看似简单的操作到底层都非常复杂,打开文件首先要扫描硬盘,找到文件的位置,然后从文件中读取一部分数据,将数据放进I/O缓冲区,放进内存;这些数据都是0、1序列,还要对照ASCII表或Unicode表”翻译“成字符,再在显示器上显示出来。这个过程如果要让程序员来完成,那简直是噩梦!
怎么办呢?操作系统想了一个很好的办法,它预先把这些复杂的操作写在一个函数里面,编译成一个组件(一般是动态链接库),随操作系统一起发布,并配上说明文档,程序员只需要简单地调用这些函数就可以完成复杂的工作,让编程变得简单有趣。这些封装好的函数,就叫做API(Application Programming Interface),即应用程序编程接口。
说得更加通俗易懂一些,别人写好的代码,或者编译好的程序,提供给你使用,就叫做API。你使用了别人代码(或者程序)中的某个函数、类、对象,就叫做使用了某个API。
操作系统已经为我们实现了很多功能,它们都被封装成了一个一个的函数,有成百上千个之多,这些函数就叫做 API。程序员要想使用某个功能,只需要调用相应的函数。Windows、Linux、Mac OS、Unix 这些常见的操作系统大部分功能都使用C语言开发,它们的 API 也以C语言的形式呈现。操作系统 API 数目众多,官方必须提供详细的说明文档(Windows API 的说明文档叫 MSDN),程序员在使用 API 时,需要频繁地查阅这些文档。
AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小AnyPopup 判断屏幕上是否存在任何弹出式窗口ArrangeIconicWindows 排列一个父窗口的最小化子窗口
各种编程语言自带的标准库其实也是API。这些API由编程语言的开发者们编写,安全、高效、健壮,为我们实现了常见的功能,让我们不用再重复造轮子。
libxml2——xml的c语言版库,2个项目使用过,win和Linux下都很犀利~~比较快捷
CURL—— 这个用的主要是使用了他的封装的http和https的请求,比较犀利,其中包含了openssl的内容
openssl——C的开源密库,可以进行证书加密和https的访问的模拟提交可以和CURL配合使用
还有很多第三方(非官方)的组织机构、公司、个人提供的代码,也是一种 API。这些代码有的免费,有的收费;有的开源,有的闭源。这些代码大都针对某个特定的应用领域编写,有时候被称为框架或者库。例如基于C语言的图形界面库GTK,基于C++的网络库ACE,基于Java的大数据处理平台Hadoop,基于Python的Web开发框架Django,基于Javascript的前端开发框架React。
全球最大的代码托管网站GitHub也贡献了很多优秀的代码,它们大都开源免费。作为开源代码库以及版本控制系统,Github拥有超过900万开发者用户。随着越来越多的应用程序转移到了云上,Github已经成为了管理软件开发以及发现已有代码的首选方法。。这些第三方的API数目众多,种类丰富,我们应该大胆去使用,尽量避免重复造轮子。
假设你想在你的窗体模块中声明一个函数,粘贴然后运行,VB会告诉你:编译错误…Declare 语句不允许作为类或对象模块中的Public(公共的) 成员。..看起来很糟糕,其实你需要做的只是在声明前面添加一个Private(私有的)。不要忘了,可是这将使该函数只在该窗体模块可用。. 在有些情况下,你会得到”不明确的名称”这样的提示,这是因为函数、常量或其他的什么东西共用了一个名称。由于绝大多数的函数都进行了别名化,亦即意味着你可以通过Alias子句使用其它的而不是他们原有的名称,你只需简单地改变一下函数名称而它仍然可以正常运行。
总结:API随处可见,它屏蔽了很多底层细节,实现了很多常用功能,大大简化了程序员的工作。用好API,事半功倍!
Collection与Collections的区别一句话概括就是后者是S曲线…哎哎哎别打…别打…别打脸QnQ
咳咳…严肃点,在之前的文章中已经讲过Collection了,它是单列集合类的根接口,用于存储一系列符合某种规则的元素,它主要的子接口分别是List和Set。
Collections则是集合工具类,用来对集合进行操作。可以理解为服务Collection集合的工具类,主要提供一系列静态方法实现对各种集合的搜索、排序、线程安全等操作
代码测试之后 ,发现我们的集合按照顺序进行了排列,可是这样的顺序是采用默认的顺序,如果想要指定顺序那该怎么办呢?
一种是比较灵活的当我需要做排序的时候在去选择的java.util.Comparator接口完成。
String类实现了这个Comparable接口(Integer也实现这接口),并完成了比较规则的定义,但是这样就把这种规则写死了,那比如我想要字符串按照第一个字符降序排列,那么这样就要修改String的源代码,修改源码这件事这是不可能的了!除非你们怂恿博主跑去sun公司修改源码,接着我就删库跑路,最后绝壁是挨最毒的打…
Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
Comparator强行对某个对象进行整体排序。可以将Comparator传递给sort方法(如Collections.sort或Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。
comparable是需要比较的对象来实现接口。这样对象调用实现的方法来比较。对对象的耦合度高(需要改变对象的内部结构,破坏性大)。comparator相当于一通用的比较工具类接口。需要定制一个比较类去实现它,重写里面的compare方法,方法的参数即是需要比较的对象。对象不用做任何改变。解耦。
接下来我们需要知道ANN是怎么训练的,假设ANN网络已经搭建好了,在所有应用问题中(不管是网络结构,训练手段如何变化)我们的目标是不会变的,那就是网络的权值和偏置最终都变成一个最好的值,这个值可以让我们由输入可以得到理想的输出,于是问题就变成了y=f(x,w,b)(x是输入,w是权值,b为偏置,所有这些量都可以有多个,比如多个x1,x2,x3……最后f()就好比我们的网络它一定可以用一个函数来表示,我们不需要知道f(x)具体是怎样的函数,从小我们就认为只要是函数就一定要是可表示的,像f(x)=sin(x)一样,但是请摈弃这样的错误观念,我们只需要知道一系列的w和b决定了一个函数f(x),这个函数让我们由输入可以计算出合理的y)
但是这个问题依然很复杂,我们把它简化一下,让(y-t)^2的值尽可能的小。于是原先的问题化为了C(w,b)=(f(x,w,b)-t)^2取到一个尽可能小的值。这个问题不是一个困难的问题,不论函数如何复杂,如果C降低到了一个无法再降低的值,那么就取到了最小值(假设我们不考虑局部最小的情况)
网络权值偏置更新问题 == f(x,w,b)的结果逼近t == C(w,b)=(f(x,w,b)-t)^2取极小值问题 == C(w,b)按梯度下降问题 ==取到极小值,网络达到最优
这个问题困扰了NN研究者多年,1969年M.Minsky和S.Papert所著的《感知机》一书出版,它对单层神经网络进行了深入分析,并且从数学上证明了这种网络功能有限,甚至不能解决象异或这样的简单逻辑运算问题。同时,他们还发现有许多模式是不能用单层网络训练的,而对于多层网络则没有行之有效的低复杂度算法,最后他们甚至认为神经元网络无法处理非线年,Paul Werbos首次给出了如何训练一般网络的学习算法—back propagation。这个算法可以高效的计算每一次迭代过程中的梯度,让以上我们的推导得以实现!!
不巧的是,在当时整个人工神经网络社群中无人知晓Paul所提出的学习算法。直到80年代中期,BP算法才重新被David Rumelhart、Geoffrey Hinton及Ronald Williams、David Parker和Yann LeCun独立发现,并获得了广泛的注意,引起了人工神经网络领域研究的第二次热潮。
这种情况下偏导很容易求得,因为我们已经知道网络的函数关系式,e=(a+b)*(b+1),这是一个没有权值干预,已知输入与输出之间关系的网络。实际当中我们只是知道e与输出之间的关系,就是上面说的C=(y-t)^2,而且会有成千上万的权值和偏置干预求导的过程。那么换个思路,能不能求输出对结果的偏导呢?
再利用上图的关系。节点c对e偏导2并将结果堆放起来,节点d对e偏导3并将结果堆放起来,至此第二层完毕,求出各节点总堆放量并继续向下一层发送。节点c向a发送2*1并对堆放起来,节点c向b发送2*1并堆放起来,节点d向b发送3*1并堆放起来,至此第三层完毕,节点a堆放起来的量为2,节点b堆放起来的量为2*1+3*1=5, 即顶点e对b的偏导数为5。简要的概括,就是从最上层的节点e开始,以层为单位进行处理。对于e的下一层的所有子节点,将1乘以e到某个节点路径上的偏导值,并将结果“堆放”在该子节点中。等e所在的层按照这样传播完毕后,第二层的每一个节点都“堆放些值,然后我们针对每个节点,把它里面所有“堆放”的值求和,就得到了顶点e对该节点的偏导。然后将这些第二层的节点各自作为起始顶点,初始值设为顶点e对它们的偏导值,以层为单位重复上述传播过程,即可求出顶点e对每一层节点的偏导数。
第一层是输入层,包含两个神经元i1,i2,和截距项b1;第二层是隐含层,包含两个神经元h1,h2和截距项b2,第三层是输出o1,o2,每条线上标的wi是层与层之间连接的权重,激活函数我们默认为sigmoid函数。
这样前向传播的过程就结束了,我们得到输出值为[0.75136079 , 0.772928465],与实际值[0.01 , 0.99]相差还很远,现在我们对误差进行反向传播,更新权值,重新计算输出。
以权重参数w5为例,如果我们想知道w5对整体误差产生了多少影响,可以用整体误差对w5求偏导求出:(链式法则)
唯一比较困难的,就是第二个方程,它给出了根据下一层的错误量δl+1计算δl的等式。为证明该等式,我们先依据δkl+1=∂C/∂zkl+1重新表达下等式δlj =∂C/∂zlj。这里可以应用链式法则:
这就是以分量形式呈现的 (BP2)。后两式在完成了BP2证明之后就不太难了,留给读者来证明。
里氏替换原则来源: 我们都知道面向对象有三大特性:封装、继承、多态。所以我们在实际开发过程中,子类在继承父类后,根据多态的特性,可能是图一时方便,经常任意重写...新功能F由类
理解 看了两天了MMU,有点眉目,记下来。只说原理,不说具体的寄存器设置。 没有MMU时候,CPU核和外部存储器直接对话。情况是这样的: 有了MMU,CPU核外部存储器只找MMU...
VC编译器设置选项并没有先后顺序,只是作者在具体开发过程碰见了不同的编译设置,进行深入了解,做此文章记录。也希望读到这篇文章的您有所收获;本文章主要参考MSDN,编译器为VC7.1,
基于Java8详细介绍了Lambda表达式的语法与使用,以及方法引用、函数式接口、Lambda复合等Java8的新特性!
的说,即一个类只负责一项职责。 1.3 场景说明 假如类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。 解决方式...
LSP,Liskov substitution principle,中文翻译为“里氏替换原则”。 这是面向对象原则中唯一一个以人名命名的原则,虽然Liskov在中国的知名度没有UNIX的几位巨匠(Kenneth Thompson、Dennis Ritchie)、GOF...
面向对象其它六大原则 单一职责原则-带你走梦幻西游(一) 依赖倒置原则(二) 开闭原则(三) 迪米特原则-带你走进梦幻西游(四) 接口隔离原则(六)里氏代换原则是由麻省理工学院(MIT)计算机科学实验室的...
‘你不知道的javascript’------笔记 之 词法作用域 不久前初识作用域,简单的认识了一下作用域的概念,然后书的后面分别介绍了词法作用域,函数作用域,块作用域,然后,今天来一起...我们
是:O2O(online To Offline)即线上到线下,其核心是把线上的消费者带到现实的商店中去,也就是让用户在线支付购买线下的商品和服务后,到线下去享受服务。 首先,线O应立足于实体店...
VC编译器设置选项并没有先后顺序,只是作者在具体开发过程碰见了不同的编译设置,进行深入了解,做此文章记录。也希望读到这篇文章的您有所收获;本文章主要参考MSDN,编译器为VC7.1,...
几年前你可能会遇到这样一个面试题:“重写和重载的区别”、而现在随着科技的更迭、面试的问题越来越高级、面试官的问题也越来越深入、此文是上述面试题的一个延伸、让你从简单的重写规则中更加深入的理解其软件工程...
第一部分:A*算法简介 写这篇文章的初衷是应一个网友的要求,当然我也发现现在有关人工智能的中文站点实在太少,我在这里 抛砖引玉,希望大家都来热心的参与。 还是说正题,我先拿A*算法开刀,是因为A*在...


