庚子年是中国传统的 60 甲子纪年法。擅长观测的古人很早就发现,每当年份执行到庚子这一年,自然灾害变多,突发事件频频,一些震动世界、影响安定的大事件也容易发生在这一年。而我们现在所处的 2020 年就是新一轮的庚子年,现在都 4 月了,很多网友都调侃说新的一年什么事情都没做,光在见证历史了。
当然了,作为一个技术博主,我并不是来给大家科普庚子年的,今天我们要说的是计算机中的一个比较危险的年份——2038 年。
2038 年问题 在说 2038 年问题前,我们需要先明白计算机是如何存储系统时间的。
在 Unix 或类 Unix 系统中,都是以 1970 年 1 月 1 日 0 点 0 分 0 秒作为时间的基准点,用秒数来表示系统时间,也即当前系统时间是从基准时间(1970 年 1 月 1 日 0 点 0 分 0 秒)走过多少秒之后的时间。
用公式简单表示就是这样:系统时间 = 基准时间 + 秒数
因为基准时间是确定的,所以我们唯一需要考虑的就是秒数应该如何保存。在当时那个年代,计算机硬件资源非常紧缺,用 16 位表示数据就已经是一个非常奢侈的选择了。因此当时的设计者都认为用 32 位存储秒数已经**“足够大”**了。所以从那个时候开始使用 32 位来表示秒数。
我们知道在二进制中,32 位数能表示的最大的数是$2^{32}-1$,不过为了能够让时间可以往前往后数,会用第一位作为正负的判断位,第一位如果为 0,则说明为正;若第一位是 1,则说明为负。因此,在 Unix 或类 Unix 系统中,这$2^{32}-1$个数被分成了 2 部分,分别是$+2^{31}-1$和$-2^{31}$。这样我们就可以以 1970 年 1 月 1 日 0 点 0 分 0 秒作为时间的基准点,往前往后每过一秒就加一个数字,依此来计算时间。
...
最近这几天区块链又粉墨登场了,新闻媒体也一直在大量报道,宣称可能要在金融界掀起一番浪潮。甚至有人说很久之前中国就出现了区块链的产物——麻将。那么区块链到底是什么,麻将和区块链又有什么关系呢?
笔者这两天也阅读了相关文献和资料,下图是我学习的一个路径,本文也是按照自己了解区块链的路径做的一些总结,篇幅较长,写这篇文章的目的也是希望能简单地向对区块链技术不了解但是想知道区块链是什么的人介绍区块链技术,因为自己在区块链方面也是一个小白,如果有错误的地方,还望各位留言指正。
区块链 -> 比特币 首先我们得先知道,区块链和比特币之间并不等同,如果要论辈分,区块链应该是比特币的爸爸,为什么这么说呢?我们先来了解下区块链是什么,以及区块链是用来干嘛的。
什么是区块链?区块链是做什么的? 一提到区块链,相信很多人都会想到什么去中心化、分布式、不可篡改之类的名词。说实话我刚开始由于姿势水平不够看到这些名词的时候也是一头雾水,《区块链技术发展现状与展望》一文给出如下定义:
狭义来讲,区块链是一种按照时间顺序将数据区块以链条的方式组合成特定数据结构, 并以密码学方式保证的不可篡改和不可伪造的去中心化共享总账(Decentralized shared ledger),能够安全存储简单的、有先后关系的、能在系统内验证的数据。
广义的区块链技术则是利用加密链式区块结构来验证与存储数据、利用分布式节点共识算法来生成和更新数据、利用自动化脚本代码(智能合约)来编程和操作数据的一种全新的去中心化基础架构与分布式计算范式。
上面的文字毕竟太过学院派了,如果用一句话来概括,区块链其实就是一种数据结构(栈和队列也是一种数据结构),既然他是一种数据结构,那区块链的作用自然也就不言而喻了:组织并存储数据。剩下的一些定语如「去中心化」、「分布式」这些无非就是对这种数据结构的修饰罢了。比特币就是应用这种技术制作的数字货币。
区块+链=区块链? 既然他和栈一样是一种数据结构,那我们总得知道这个数据结构长什么样子吧。我们把区块链拆分成**「区块」和「链」**就会明白区块链长什么样子了。
区块 上图是一个**区块(Block)**示意图,每个区块包含两个部分:
区块头(Block Header):记录当前区块的特征值(里面存放的内容我们稍后再说)
区块体(Block Body):存放的数据
所以,区块就是一种存放数据的东西,可以近似的理解为链表中的节点。
链 把许多上图那样的区块连接在一起就形成了区块链,如下图所示:
想要形成一个链,那总得有头吧,链头的区块学名叫做创世区块(Genesis Block)。前一个区块称为后一个区块的父区块,反之则称为子区块。 所以,其实区块链就长上面那样,没什么神秘的。
这时我想肯定会有人问了,你说把区块连接在一起他们就能连接在一起了吗?他们之间是怎么连接的呢?
如何链接 这里我也不卖关子了,子区块与父区块是通过父区块的 哈希(Hash) 值建立链接的。这里又引入一个新的概念,什么是哈希呢?
所谓「哈希」就是计算机可以对任意内容,计算出一个长度相同的特征值。区块链的哈希长度是 256 位,这就是说,不管原始内容是什么,最后都会计算出一个 256 位的二进制数字。而且可以保证,**只要原始内容不同,对应的哈希一定是不同的。**因此我们可以得到两个推论:
推论 1:每个区块的哈希都是不一样的,可以通过哈希唯一标识区块。 推论 2:如果区块的内容变了,它的哈希一定会改变。 所以我们只需要在每个区块的区块头存放上个区块的哈希值即可。就是下图红线标注的地方。
至于如何计算出这个哈希值,不同的区块链有不同的计算方法,这里不多说。
下面这篇文章介绍了比特币是如何计算 Block Hash 的,有兴趣的可以阅读了解下。👇
https://www.jianshu.com/p/4187a7352769
为什么需要区块链? 看了上面的内容后相信你应该就明白什么是区块链了。但是肯定就会有人说,说到底这不就是链表吗,为什么国家还要大力发展区块链产业,甚至上升到了到战略层面呢?
的确,区块链的技术原理并不复杂,但是他的『社会意义』却是巨大的。
区块链本质上是一种解决信任问题、降低信任成本的技术方案,其目的就是为了去中心化。
好了,这里又出现了一个新的概念,去中心化?这个名词只要一提到区块链就一定会被提到,所以你一定想知道去中心化到底是什么。不急,在谈去中心化之前,我们先谈一下另一个词——信任。
信任 对于信任一词,维基百科给出的定义如下:
可能你还是不太能理解,我们再来举个很常见的例子:
近视的人想要摘下眼镜一般都需要做手术,但是你不清楚这个手术做了之后是否真的可以恢复视力,所以你去找专家,这个专家是全国非常有名的眼科医生,他告诉你这个手术做完是可以恢复视力的,所以你就去做手术了。
还有一种情况是,你在做手术之前问了之前做过这个手术的亲戚朋友,他们都说这个手术做完之后可以恢复到正常视力,你觉得他们都成功了,所以你就去做手术了。
但如果一个小诊所的医生告诉你,我们诊所也可以帮你做这个手术,做完也能帮你恢复视力,你会信吗?我想你可能就要好好考虑下了。
这就是所谓的信任的力量。你不会信任一个没有足够信用度的单独个体,但你会信任一堆个体或者有足够信用度的单独个体。
在金融领域,我们平常能接触到的银行就是这个有足够信用度的个体(中心)。
去中心化 仔细想一下上面那个例子,为什么我们会相信眼科专家而不相信小诊所的医生,因为相较于小诊所的医生,眼科专家有更多的信用成本,所以我们往往要为眼科专家付更多的费用。
...
最近遇到了一个和多线程有关的事,顺便简单复习了下相关概念,稍后举个栗子 🌰 来解释下。
进程 and 线程 进程我们都知道,就是应用程序的启动实例。比如我们运行一个游戏,打开一个软件,就是开启了一个进程。
而线程从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。
我们可以简单的理解:为了做一件事,我开了一个进程,为了让这件事更有效率的完成,我开了多个线程。
从找对象入手加深理解 如果这么说还是不清楚的话,我们以一个找对象的例子来加深理解:
读研了,望着身边的小伙伴一个个都是成双成对,笔者有一个万年单身的好基友就跟一条酸菜鱼似的(又酸又菜又多余),想着要不也找个女朋友吧?于是就创建了一个名为**「找对象」的进程**。但是学校女生太多了,如果一个一个试的话不知道啥时候才能脱单。这时候,万能的度娘给出了建议,为什么不同时下手呢?
于是,他就创建了两个「撩妹」的线程,每个线程负责撩一个妹子。但这时就有问题出来了。
虽然他可以同时撩两个妹子,但是有些事情就是没办法同时和两个妹子做,比如上课、吃饭、散步。这个时候就需要**「数据保护」。做这些事情的时候,他一次只能跟一个妹子做,这就叫做「临界区」。他撩的两个妹子,一个是红玫瑰,一个是白玫瑰,各有各的特点,这是她们的「私有属性」。这两个妹子都可以跟他约会,此时他就是一个「共享内存」。如果某一天他跟其中一个妹子在外面约会,那另一个撩妹线程就只能「阻塞」了。但是为了防止后院起火,不让另一个妹子不爽,他就只能发条朋友圈说自己在学习,不想被打扰,这就叫「互斥锁」。同时为了不让她们影响对方的存在,他用 QQ 叫着其中一个的小名,微信却是另一个的情侣头像,这就是「消息传递」**。
上述两个线程在某种意义上就构成了**「竞态条件」(个人认为叫做「竞争状态」会更好)。如果他只有这两个线程的话,想要完成「找对象」这个进程,就只能看这两个线程谁的执行效率更高(其实就是看谁先运行完)**了。这么一看,我的好基友貌似很快就可以完成「找对象」这一进程了,因为无论是哪个线程,只要有一个「撩妹」线程结束了,整个进程也就结束了。
但是在结束前**可能会出现一些问题(注意这里是可能),如果他在排约会档期时一旦没有进行良好的调度,就很有可能会出现两个妹子约在同一天约会,基友却没办法到达的情况,这种情况就叫「死锁」,即较长时间的等待或资源竞争。亦或是如果不幸被两个妹子都发觉了对方的存在,却又为表大度,你让我我让你,最终导致「找对象」进程无法进行下去,这就叫做「活锁」。 如果此时出现了一个「工具人」妹子,主动倒追我基友,这样的话即使被加入了「找对象」的进程,也可能会因为一系列问题始终没法和他单独约会(毕竟还有两个「撩妹」线程在进行着),这种情况就叫做「饥饿」**。 这三种情况总结一下就是:
死锁:争来争去 谁也得不到 活锁:让来让去 谁都不拥有 饥饿:排多久 都轮不到自己 倘若我基友最后撩成功的女朋友并不是他最喜欢的那个人,即最终的运行结果和预期不同,这就叫**「线程不安全」。反之,如果最后撩成功的妹子是他最喜欢的,即最终的结果和预期相同,那这个就叫「线程安全」**。
这么一看,真是人生如戏。只是可悲的是,我本以为现在执行的是一个单进程,却没想到也只是别人的一个线程罢了。
如果你觉得我的文章还不错,不妨扫描下方二维码关注我,你的支持是我前进的最大动力 💪
前言 相信很多人在制作自己的第一个网站的时是很激动的。我们知道,在一个网站项目中,页面里经常会有许多 JavaScript 以及 CSS 的引用,如果是直接引用项目内文件的话,他们可能是这样的:
这种方式的优点是开发省力,发布省力,对服务器要求小,省钱,没有具体公网接入需求。
然而如果你的网站里面有很多图片或者视频并且需要部署到公网上时,网站的访问速度一定会让你倍感崩溃。就像下面这张图 👇
这时候肯定会有推荐你使用 CDN 来加速网站里的一些 JavaScript 和 CSS 文件,如下所示:
其实上面的图片就已经使用到 CDN 了。那到底什么是 CDN 呢?
在解释什么是 CDN 之前,我们先来看一个身边非常常见的案例—— 网购。
京东自营与淘宝的购物体验 相信现在应该没有人没用过淘宝和京东的,在说 CDN 之前我们先来说下我在淘宝和京东的购物体验。下面是我在使用这两个电商平台时的情况:
在淘宝买第三方店家商品 在京东购买自营商品 之前我在淘宝买了一个雷电 3 的扩展坞,发货地是深圳,花了三天才到南京,如果收货地是河南呢?新疆呢?我想时间就更长了。可是我在河南的同学在京东(自营)买了一个手机下午购买的第二天早晨就收到货了(并不是给京东打广告)。这是为什么呢?
我们在用京东购物的时候,如果仔细观察的话可以发现,京东自营会根据我们的收货地点,在全国范围内找离我们最近、送达最快的仓库,比如我在南京下的订单,他可能就会从上海甚至直接从南京发货;如果是在洛阳下单可能就会从郑州发货。这样做的好处就是不管我们在南京,还是乌鲁木齐,我们的收货时间会大大减少。CDN 就类似于京东建立的这种仓储系统。
从网购到 CDN 不知道上面的描述是否清楚,这里为了加深理解,我制作了下面的流程对比图:
为了让货物更快的送到买家手中,京东建立了这种仓储系统;类比到网络中,为了让用户更快地加载网页(可以理解为服务器给浏览器送页面),CDN 横空出世了。
CDN 的全称是 Content Delivery Network,即内容分发网络。其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN 系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上(如下图所示)。其目的是使用户可就近取得所需内容,解决 Internet 网络拥挤的状况,提高用户访问网站的响应速度。
从“直播”理解一些和 CDN 有关的名词 从上面的描述中我们得知了 CDN 的作用以及大概原理,但是其中的细节并没有展开来说。其实 CDN 的一些细节通常会和一些名词联系上,例如负载均衡、源站之类的。同样的,我们以一个身边的例子——“直播”——来讲解这些和 CDN 有关的名词。
我们知道,视频其实是由一帧一帧的图片组成的,所以直播的时候我们收到的视频画面的流程可以近似理解为下面这样 👇
然而事实是这样的吗?当然不是!一个主播怎么可能只有一个观众,所以应该是下面这样 👇
上图的方式是主播把相同的数据同时传给多个不同的观众,这当然是非常愚蠢的方式,同样的数据被传了多次,主播端的瓶颈非常明显,比如有 1000 个观众同时观看的时候,主播端根本无法承担这么多的数据传输。
...
前言 学妹这学期新开了一门课《Script 及 AJAX 开发技术》,然而临近学期末,她突然跑来问我:到底什么是 AJAX ?相信很多人(尤其是前端)在写代码的时候经常会用到 AJAX 技术,但是如果真要说出个所以然,可能还会有些困难。其实简单概括下,AJAX 就是一种利用 JavaScript 向服务端发起请求,并获得服务端响应的技术。它的特点是异步请求,局部刷新。
Tips:这里我将技术二字加粗了,是因为很多初学者会以为 AJAX 是一个库/框架,类似于JQuery/Vue之类的,因而有很多初学者会提出该怎么安装 AJAX 的问题。事实上 AJAX 是一种技术。
虽然概括起来很简单,但是 AJAX 技术的一些细节仍然值得我们思考,接下来我会详细的介绍。
AJAX 解决的问题 我们刚才说过了,AJAX 是一种发送请求的技术,那在 AJAX 被发明前,浏览器是如何请求的呢?
地址栏。用户在地址栏输入 http://baidu.com ,按回车,就向 http://baidu.com 发起了一个请求。(同时页面刷新) a 标签。用户点击页面中的 a 链接,也会发起一个请求。(同时页面刷新) img 标签。页面中如果有 img 标签,那么就会发起一个对此图片的请求(页面没有刷新,但是只能请求图片)类似的还有 link 标签、script 标签,都可以对一类文件的请求。 在这三种方式中,除了第三种,其他两种方式想要发送一个请求,就必须要刷新页面,如果页面只有展示内容的话刷新一下自然无所谓,但倘若一个页面有很多的表单内容需要填写,而你在最后填写完成提交的时候才告诉你,其中某一个地方不符合要求,要你回去重填,然后刷新一下页面,内容都消失了,怕是当时就可能会气的暴走了吧。
也正是这种极端的用户体验让微软创新地开发了一个接口 ActiveXObject(“Microsoft.XMLHTTP”),并在 IE 5.0 中开放给开发者用。通过该接口,浏览器可以向服务器发送请求并取回所需的数据,并在客户端采用 JavaScript 处理来自服务器的回应。这就是 AJAX 的前身。随后这种技术被谷歌的开发人员发现并运用在 Gmail 中,再然后就是 W3C 制定了一个标准用来规范 AJAX,至此 AJAX 算是正式成为每一个前端开发者的必备技能了。
通过 AJAX 技术,服务器和浏览器之间交换的数据大量减少,服务器回应更快了。同时,很多的处理工作可以在发出请求的客户端机器上完成,因此服务端的负荷也减少了许多。
AJAX 的原理 那 AJAX 的实现原理又是什么呢?我们先来看一下 AJAX 的定义,以下内容摘自维基百科:
...
前几天有个学妹问我为什么在浏览器里面输了网址就会显示出来页面,虽然这个现象很常见,但是要想解释清楚确实有些小困难,当时也只是简单的回答了她,现在想趁着这个机会好好整理下相关知识。整理完才觉得其实就和我们去一个地方找人是一个道理。所以说艺术源于生活却又高于生活,技术同样如此。
在回答这个问题前, 我们先来了解下我们平常说的那个网址到底是啥?
网址的学名叫做统一资源定位符(Uniform Resource Locator, 常缩写为URL), 我们知道现在的互联网其实就是由众多资源所构成的一张巨大的网, 如何定位那些资源就是靠的 URL, 因此我们也可以把 URL 理解为是网络上资源的“门牌号“, 我们在浏览器中输入网址, 就相当于开一辆车(浏览器)去找一个地址(URL)
1. 缓存查找 如果你要出门找一个地方, 第一想法肯定是先想这个地方你有没有去过, 你要是去过的话那就不需要问人直接过去就好了。 我们的系统也是这么想的。 当你在浏览器中输入了 URL 之后, 浏览器会先查看 浏览器缓存 中有没有这个地址, 如果没有那就再去 系统缓存, 如果系统缓存还没有, 那就去路由器缓存找, 总之只要缓存中有, 就说明有这个资源, 那浏览器直接显示出来就好了。
Tips: 这里说下 hosts 文件 , hosts 是一个没有扩展名的系统文件, 可以用记事本等工具打开, 其作用就是将一些常用的网址域名与其对应的 IP 地址建立一个关联“数据库”, 当用户在浏览器中输入一个需要登录的网址时, 系统会首先自动从 hosts 文件中寻找对应的 IP 地址,一旦找到, 系统会立即打开对应网页, 如果没有找到, 则系统会再将网址提交 DNS 域名解析服务器进行 IP 地址的解析。 需要注意的是, hosts 文件配置的映射是静态的, 如果网络上的计算机更改了请及时更新 IP 地址, 否则将不能访问。
2. DNS 解析 如果你认得去那个地址的路自然是最好, 那如果你根本就没去过那咋办? 肯定会有人说导航, 但并不是所有的地方都是导航能搜到的, 这个时候我们自然而然就会想着去问路人了。 浏览器也是这样的, 如果在本地缓存中没有找到想要的资源, 那就只能去其他网络上的机器中寻找我想要的资源了。 那你怎么知道你要的资源在那台机器上? 这时, DNS 就横空出世了。
...
Image by pangziai on Pixabay
今天是一年一度的植树节,说到树,我就想到了《西游记》中的古树精,今年下半年。。。好了好了,不皮了,我们直接开花。今天就趁着植树节来种一棵我们程序员的“树”吧。
什么是“树”? 在种树之前,我们先来了解下什么是树?看个例子:
不对不对,放错了,应该是下面这个:
维基百科对于树的定义是:
在计算机科学中,树(英语:tree)是一种抽象数据类型(ADT)或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由 n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
说白了,只要是形如上图的数据结构就叫树。
二叉树 自然界中有“迎客松”、“轩辕柏”这样出名的树,我们今天要种的树也是我们 IT 圈里面的扛把子——“二叉树”。
二叉树是数据结构中一种重要的数据结构,也是树表家族最为基础的结构之一。
二叉树的特点是每个结点最多有两个子树,左边的叫做左子树,右边的叫做右子树,二叉树要么为空,要么由根结点、左子树和右子树组成,而左子树和右子树分别是一棵二叉树。 下面这棵树就是一棵二叉树。
常见术语 结点(node):上图中的 A、B、C。。。就是一个结点 结点的度:一个结点含有的子树的个数称为该结点的度 树的度:一棵树中,最大的结点的度称为树的度 深度:对于任意节点 n , n 的深度为从根到 n 的唯一路径长,根的深度为 0; 高度:对于任意节点 n , n 的高度为从 n 到一片树叶的最长路径长,所有树叶的高度为 0; 种树 接下来的代码均用 Java 展现,完整代码可在公众号「01 二进制」后台回复“二叉树”查看。
现在我们就开始种一棵如上图的树吧。根据定义,我们了解到,结点是一棵二叉树最重要的元素,而作为一个结点,必须满足以下条件:
根结点 左子树和右子树 因此我们可以创建一个结点类(TreeNode):
class TreeNode { String data; TreeNode left; TreeNode right; TreeNode(String data) { this.data = data; } } 有了这个结点类之后我们就可以创建出一个如上图的树了:
...
最近开始了有关机器学习方面知识的学习,自己啃书本的时候一些概念枯燥无味,所以借着做笔记的机会来简单理解其中的一些概念,如有谬误,还望指出。😊
什么是人工智能? 我看过很多博客解释什么是人工智能,我觉得还不如一句话一张图解释的简洁明了。让机器实现原来只有人类才能完成的任务,这个操作就是人工智能。
下图所示就是让机器模拟人各种能力的人工智能领域示意图:(图片我是在逛知乎的时候发现的,地址贴在文末)
什么是机器学习? 在解释什么是机器学习之前,我们先来举一个让每个程序员都头疼的问题:
找对象 作为一个程序员,找对象自然是个非常紧迫的问题,那找对象总要有个要求吧 🤔
啥?活的?能动?骨骼轻奇的我怎么可能只有这两点要求啊 🙊 显然我是希望找一个好的女朋友啊(毕竟要带出去撑场面的啊),所以应该怎么找呢?
爱美之心,人皆有之。长得好看的妹子肯定比长得丑的妹子更优秀啊,所以这时我就有了一个简单的规则了:只挑选长得好看的女生的当女朋友。所以还等什么?快去朋友圈看看哪些漂亮的女生还是单身啊。是不是 So easy?
当!然!不!是!
生活总是充满了艰辛 张无忌的麻麻说过:
当你网恋奔现的时候你会发现,那些朋友圈里的都是照骗,你懵逼了。。。很显然,只看女生照片找对象这个方法是很片面的,找到一个好的女朋友的因素有很多而并不只是根据女生的颜值。
在经过了大量思考(并且参考了众多好友的女朋友)之后,你又得出了一个结论:身材好同时颜值高的女生更容易吸引你。同时身材一般但颜值高的好友中只有一半左右能让你感兴趣。
这时你再带着你得出的结论去找女生的时候,才知道原来妹子已经脱单好久,只是把你当朋友。。。但是心好的妹子为了安慰你便把她的闺蜜推给了你。然后你发现你之前的结论不适用了,所以只能重新开始约朋友圈的妹子。
假设过了好久好久之后,你成功的总结了一个找妹子的经验,找到了一个优秀的另你满意的妹子了,你很开心的和她在一起了。丑媳妇也要见公婆的,终于到了你把女朋友带回家给家长见面的时候了,你爸妈说,这女生太漂亮了,你管不住,坚决反对。
在你爸妈的反对下,你只能选择无奈的和妹子 say goodbye👋。最后的最后你和你爸妈摊牌,然后将你的择偶规则告诉你的家人,在他们的筛选下,你终于找到了符合**“所有”**预期标准属性的女朋友了。
是不是觉得很 dan 疼? 回想一下上述的场景,是不是觉得十分 dan 疼,虽然最终结果是你找到了一个满意的女朋友,但是在找对象的过程中,你需要不断的更换标准(属性),而且每当你需要用一个新的标准(属性)去衡量一个妹子的时候,你只能手动更改你自己的规则。并且你需要了解所有繁杂的影响女朋友质量的因素(比如颜值、身材、贴心程度、可爱程度等等)。如果这些因素足够复杂,你很难手动分类所有类型的女生而做出精确的规则。
并且,不断的和不同的女生谈恋爱、试错不仅浪费时间,名声也不好。说不定还会被扣上一定渣男的帽子。
来类比下? 其实上述就是一个非常不典型的机器学习的例子,我们来类比下:
机器学习(ML)
你可以从朋友圈随机挑选一些女生(假设你的异性缘足够的好)作为样本(training data),然后列出所有女生的属性,比如身高、颜值、身材、学历、工作,等等(features),以及是否贴心、黏人度、孝心,等等(output variables)。将这些抽象化的数据在机器学习算法里运行(classification/regression),则 ML 算法构建一个模型:女生的属性——女生的质量。
然后等到下次你又遇见了一个女生了,你就可以用眼睛扫一下检查女生的属性(身材、颜值等)了(test data),然后提供给 ML 算法,他就会根据之前生成的模型(model)预测这个妹子最终和你走到一起的可能有多大。
其实在机器学习构建模型过程中,内部使用的规则也许和上述例子中类似,但是也有可能是更复杂的规则,不过这些你并不需要关心。
你现在再去找对象就有很大信心了,而且更重要的时候,随着时间你的 ML 算法会自我提升(reinforcement learning),当预测错误的时候(恋爱谈不下去就分手)矫正自身,随着读取更多的 training data 预测也会越来越精准。但是,最流弊的一点在于,你可以利用相同的算法而训练出不同的模型(model),找女朋友可以用这个模型,那找秘书呢?(仿佛发现了什么不得了的事情 🤓,随便你想要训练出什么模型只要你高兴就好 )
所以说对机器学习的最简单的理解,便是:
使用某种算法来对已有数据进行解析、学习,然后对真实世界中的数据/事件作出决策/预测。
那深度学习又是啥? 深度学习,是实现机器学习的技术。对机器学习来说,特征提取并不简单。特征工程往往需要大量的时间去优化,而此时,深度学习便可以自动学习特征和任务之间的关联,还能从简单特征中提取复杂的特征。
深度学习是机器学习的许多方法之一,其他方法包括决策树学习、归纳逻辑程序设计、聚类、强化学习和贝叶斯网络等。
那深度学习是如何寻找那些复杂特征的呢?
他是通过建立、模拟人脑进行分析学习的神经网络,它模仿人脑的机制来解释数据,如图象、声音、文本。其产生的灵感来自于大脑的结构和功能,即许多神经元的互联。
下图是我在知乎上看见的一个非常有趣的回答:
推荐大家去阅读下这个回答:👇
人工智能、机器学习和深度学习的区别? - 图普科技的回答 - 知乎https://www.zhihu.com/question/57770020/answer/418117913
...
上篇文章介绍了基于用户的协同过滤算法,该算法在一些网站(如 Facebook)中得到了应用,但该算法有一些缺点。首先,随着网站的用户数目越来越大,计算用户兴趣相似度矩阵将越来越困难,其运算时间复杂度和空间复杂度的增长和用户数的增长近似于平方关系。其次,基于用户的协同过滤很难对推荐结果作出解释。因此,著名的电子商务公司亚马逊提出了另一个算法一基于内容的协同过滤算法。
什么是基于内容的协同过滤算法 在进入本文的正题之前,先打开网易云音乐看下今天的日推:
看了上述的标记,是不是瞬间理解了为啥用网易云听音乐的时候会有上瘾的感觉,因为他给你听的都是你爱听的啊。就跟小时候我妈给我做菜是一样的,今天知道我喜欢吃红烧肉,明天为了照顾我的喜好又为了保证不重样,第二天就给我做了糖醋排骨,久而久之产生了依赖性,体重也开始飙升了。
上述就是 基于内容的协同过滤算法(Item-based collaborative filtering,简称 ItemCF) 在生活中常见的案例,该算法给用户推荐那些和他们之前喜欢的内容相似的内容。比如,该算法会因为你购买过《数据挖掘导论》而给你推荐《机器学习》。不过,ItemCF 算法并不利用内容的内容属性计算内容之间的相似度,它主要通过分析用户的行为记录计算内容之间的相似度。该算法认为,内容 A 和内容 B 具有很大的相似度是因为喜欢内容 A 的用户大都也喜欢内容 B。
事实上,由于人和人之间的差异性远大于内容和内容之间的差异(不然怎么会说你女朋友翻脸比翻书还快呢 🙈),ItemCF 算法算是目前业界应用最多的算法。无论是淘宝首页猜你喜欢,还是网易云音乐、哔哩哔哩、YouTube,其推荐算法的基础都是该算法。
Tips:基于内容的协同过滤算法可以利用用户的历史行为给推荐结果提供推荐解释,比如上图中网易云日推的标签,会告诉你是根据你收藏的某某单曲推荐的。
基于内容的协同过滤算法 如果你理解了我的上一篇文章《从网易云日推浅谈个性化推荐系统(1)–基于用户的协同过滤算法》,那你也很容易就可以联想到想要实现一个基于内容的协同过滤需要有以下两步:
计算内容之间的相似度。
根据内容的相似度和用户的历史行为给用户生成推荐列表。
计算内容之间的相似度 1.确定计算相似度的公式 很显然,步骤(1)的关键就是计算两个内容之间的相似度,亚马逊显示相关内容推荐时的标题是 “Customers Who Bought This Item Also Bought” (购买了该商品的用户也经常购买的其他商品) ,相当于就下了一个定义,根据这个定义,我们可以用下面的公式定义内容的相似度:
$$W_{ij}=\frac{\left | N(i)\cap N(j) \right |}{\left | N(i) \right |}$$
这里,分母$\left | N(i) \right |$是喜欢物品$i$的用户数,而分子$\left | N(i)\cap N(j) \right |$是同时喜欢物品$i$和物品$j$的用户数。因此,上述公式可以理解为喜欢物品$i$的用户中有多少比例的用户也喜欢物品$j$。
上述公式虽然看起来很有道理,但是却存在一个问题。如果物品$j$很热门,很多人都喜欢, 那么$W_{ij}$就会很大,接近 1。因此,该公式会造成任何物品都会和热门的物品有很大的相似度,这对于致力于挖掘长尾信息的推荐系统来说显然不是一个好的特性。为了避免推荐出热门的物品, 可以用下面的公式:
$$W_{ij}=\frac{\left | N(i)\cap N(j) \right |}{\sqrt{\left | N(i)\left | \right |N(j) \right |}}$$
...
这是 2019 年的第一篇文章,因为最近导师给了一个新的任务,有关某 app 的个性化推荐的,正好自己也是第一次学习这方面的知识,便想着汇总整理下。前人栽树,后人乘凉,因为篇幅原因,这一部分准备分开来叙述,本篇主要和大家介绍基于用户的协同过滤算法,希望可以对大家有所帮助,如有谬误,还望指正!
什么是个性化推荐系统? 其实个性化推荐系统早已渗透进我们的生活了,网易云音乐的“每日推荐”,淘宝的”猜你喜欢“,这些都是生活中非常常见的个性化推荐的案例。如今,随着大数据的发展,个性化推荐早已涉及诸多领域,比如电子商务(京东淘宝)、电影和电视网站(youtube)、个性化音乐网络电台(网易云音乐)、社交网络(QQ)、个性化阅读(微信读书)、基于位置的个性化服务(美团)等。推荐算法的本质是通过一定的方式将用户和物品联系起来,而不同的推荐系统也会根据实际情况采取不同的推荐方式。
一般来说一个完整的推荐系统一般包括以下三个参与方:
被推荐对象 推荐物品的提供者 提供推荐系统的网站 以网易云音乐的日推为例:
首先,推荐系统需要满足用户的需求,给用户推荐那些令他们感兴趣的音乐。其次,推荐系统要尽量让各个歌手的歌都能够被推荐给对其感兴趣的用户,而不是只推荐几个大流量歌手的歌。最后, 好的推荐系统设计,能够让推荐系统本身收集到高质量的用户反馈,不断完善推荐的质量,增加用户和网站的交互,提高网站的收入。如下图所示:
什么是好的推荐系统? 想要评判一个东西好不好,一定要有个标准。那么推荐系统好坏的标准是什么呢?试想一下为什么大家都喜欢网易云音乐的每日推荐而不喜欢今日头条的每日推送呢?最直观的感受就是网易云的日推歌曲你爱听,而头条的推送你很讨厌。所以说预测准确度是推荐系统领域的重要指标(没有之一)。
好的推荐系统不仅仅能够准确预测用户的行为,而且能够扩展用户的视野,帮助用户发现那些他们可能会感兴趣,但却不那么容易发现的东西(比如网易云音乐经常给你推送那些非常好听但是比较冷门的歌曲)。同时,推荐系统还要能够帮助商家将那些被埋没在长尾中的好商品介绍给可能会对它们感兴趣的用户。
协同过滤(Collaborative Filtering) 为了让推荐结果符合用户口味,我们需要深入了解用户。如何才能了解一个人呢?《论语·公冶长》中说“听其言,观其行”,也就是说可以通过用户留下的文字和行为了解用户兴趣和需求。
实现个性化推荐的最理想情况是用户能主动告诉系统他喜欢什么,比如很久之前注册网易云音乐的时候会让用户选择喜欢什么类型的歌曲,但这种方法有 3 个缺点:首先,现在的自然语言理解技术很难理解用户用来描述兴趣的自然语言;其次,用户的兴趣是不断变化的,但用户不会不停地更新兴趣描述;最后,很多时候用户并不知道自己喜欢什么,或者很难用语言描述自己喜欢什么。
因此,我们需要通过算法自动发掘用户行为数据,从用户的行为中推测出用户的兴趣,从而给用户推荐满足他们兴趣的物品。
基于用户行为分析的推荐算法是个性化推荐系统的重要算法,学术界一般将这种类型的算法称为协同过滤算法(Collaborative Filtering Algorithm)。顾名思义,协同过滤就是指用户可以齐心协力,通过不断地和网站互动,使自己的推荐列表能够不断过滤掉自己不感兴趣的物品,从而越来越满足自己的需求。
既然是基于用户的行为分析,就必须要将用户的行为表示出来,下表给出了一种用户行为的表示方式(当然,在不同的系统中,每个用户所产生的行为也是不一样的),它将个用户行为表示为 6 部分,即产生行为的用户和行为的对象、行为的种类、产生行为的上下文、行为的内容和权重。
表示 备注 user id 产生行为的用户的唯一标识 item id 产生行为的对象的唯一标识 behavior type 行为的种类(比如说是点赞还是收藏) context 产生行为的上下文,包括时间和地点等信息 behavior weight 行为的权重(如果是听歌的行为,那么权重可以是听歌时常) behavior content 行为的内容(如果是评论行为,那么就是评论的文本) 随着学术界的大佬们对协同过滤算法的深入研究,他们提出了很多方法,比如基于邻域的方法(neighborhood-based)、隐语义模型(latent factor model)、基于图的随机游走算法(random walk on graph) 等。在这些方法中,最著名的、在业界得到最广泛应用的算法是基于邻域的方法,而基于邻域的方法主要包含下面两种算法:
基于用户的协同过滤算法(User-based Collaborative Filtering),简称 UserCF 或 UCF,这种算法给用户推荐和他兴趣相似的其他用户喜欢的物品。 基于物品的协同过滤算法(Item-based Collaborative Filtering),简称 ItemCF 或 ICF,这种算法给用户推荐和他之前喜欢的物品相似的物品。 基于用户的协同过滤算法 在一个在线个性化推荐系统中,当一个用户 A 需要个性化推荐时,可以先找到和他有相似兴趣的其他用户,然后把那些用户喜欢的、而用户 A 没有听说过的物品推荐给 A。这种方法称为基于用户的协同过滤算法。
...