程序员面试要准备些什么东西

程序员面试要准备些什么东西,第1张

面试前的准备

简历

1 千万别给自己挖坑

在面试的时候,面试官都会针对简历上技术能力、工作经历、项目经验等提出一些细节上的问题,所以你写下的都些东西必须是真实,并且是非常了解。

2 要有辨识度

通常一个职位可能收到的简历比较多,很多时候,你的简历甚至根本没被HR看到。那么,怎样让自己的简历脱颖而出呢?首先,简历要有“辨识度”,要让面试官看完这个简历,就很想见见这个人。

3 面试前最好进行一个“模拟面试”

其实自己在制作简历的时候,就像写程序一样自己是很难发现bug的,因此在面试前最好找朋友、老师或同学帮你来一场“模拟面试”,这样也许会发现一些意想不到的问题。

4 针对不同的公司要对简历进行微调

比如对方是个做电商。而你恰好做过类似项目,就可以将该部分的项目介绍着重突出以下,比如排列到最前面。

充分准备相关的专业知识

可以在网上收集一些相关的面试题,有时面试官也可能会照着网上的内容来问,所以网上一些比较热门的题目也可以关注一些,然后对照自己的经验组织成自己的语言。

项目经验

项目的研发背景、整体业务流程、开发周期、负责的模块、技术实现细节、技术亮点等。自己做过的每个项目都要整理清楚。

了解热门前沿技术

比如你面试的是 iOS 开发岗位,除了 OC 你还能聊聊最新版本的 Swift;比如现在微信小程序开发又火起来了,你也在关注和学习,甚至能解决面试官的一些问题。了解这些热门的前沿技术绝对会成为你面试时的加分点。

线性代数是什么?

在大学数学学科中,线性代数是最为抽象的一门课,从初等数学到线性代数的思维跨度比微积分和概率统计要大得多。很多人学过以后一直停留在知其然不知其所以然的阶段,若干年之后接触图形编程或机器学习等领域才发现线性代数的应用无处不在,但又苦于不能很好地理解和掌握。的确,多数人很容易理解初等数学的各种概念,函数、方程、数列一切都那么的自然,但是一进入线性代数的世界就好像来到了另一个陌生的世界,在各种奇怪的符号和运算里迷失了。

我在初接触线性代数的时候简直感觉这是一门天外飞仙的学科,一个疑问在我脑子里浮现出来:

如果看到这个问题,你的反应是“这还用问,数学当然是客观的自然规律了”,我一点儿都不觉得奇怪,我自己也曾这样认为。从中学的初等数学和初等物理一路走来,很少人去怀疑一门数学学科是不是自然规律,当我学习微积分、概率统计时也从来没有怀疑过,唯独线性代数让我产生了怀疑,因为它的各种符号和运算规则太抽象太奇怪,完全对应不到生活经验。所以,我还真要感谢线性代数,它引发了我去思考一门数学学科的本质。其实,不止是学生,包括很多数学老师都不清楚线性代数到底是什么、有什么用,不仅国内如此,在国外也是这样,国内的孟岩写过《理解矩阵》,国外的Sheldon Axler教授写过《线性代数应该这样学》,但都还没有从根本上讲清楚线性代数的来龙去脉。对于我自己来讲,读大学的时候没有学懂线性代数,反而是后来从编程的角度理解了它。很多人说数学好可以帮助编程,我恰好反过来了,对程序的理解帮助了我理解数学。

本文的目标读者是程序员,下面我就带各位做一次程序员在线性代数世界的深度历险!既然是程序员,在进入线性代数的领域之前,我们不妨先从考察一番程序世界,请思考这样一个问题:

为什么要问这样一个看起来很蠢的问题呢?因为它的答案显而易见,大家对天天使用的程序语言的认识一定胜过抽象的线性代数,很显然程序语言虽然包含了内在的逻辑,但它们本质上都是人为的设计。所有程序语言的共同性在于:建立了一套模型,定义了一套语法,并将每种语法映射到特定的语义。程序员和语言实现者之间遵守 语言契约:程序员保证代码符合语言的语法,编译器/解释器保证代码执行的结果符合语法相应的语义 。比如,C++规定用new A()语法在堆上构造对象A,你这样写了C++就必须保证相应的执行效果,在堆上分配内存并调用A的构造函数,否则就是编译器违背语言契约。

从应用的角度,我们能不能把线性代数视为一门程序语言呢?答案是肯定的,我们可以用语言契约作为标准来试试。假设你有一个图像,你想把它旋转60度,再沿x轴方向拉伸2倍;线性代数告诉你,“行!你按我的语法构造一个矩阵,再按矩阵乘法规则去乘你的图像,我保证结果就是你想要的”。实际上,线性代数和SQL这样的DSL非常相似,下面来作一些类比:

所以,从应用的角度看, 线性代数是一种人为设计的领域特定语言(DSL) ,它建立了一套模型并通过符号系统完成语法和语义的映射。实际上,向量、矩阵、运算规则的语法和语义都是人为的设计,这和一门语言中的各种概念性质相同,它是一种创造,但是前提是必须满足语言契约。

为什么要有线性代数?

可能有人对把线性代数当成一门DSL不放心,我给你一个矩阵,你就把我的图形旋转了60度沿x轴拉伸了2倍,我总感觉不踏实啊,我都不知道你“底层”是怎么做!其实,这就像有的程序员用高级语言不踏实,觉得底层才是程序的本质,老是想知道这句话编译成汇编是什么样?那个 *** 作又分配了多少内存?别人在Shell里直接敲一个wget命令就能取下一个网页,他非要用C语言花几十分钟来写一堆代码才踏实。其实,所谓底层和上层只是一种习惯性的说法,并不是谁比谁更本质。 程序的编译和解释本质上是不同模型间的语义映射 ,通常情况下是高级语言映射为低级语言,但是完全也可以把方向反过来。Fabrice Bellard用JavaScript写了一个虚拟机,把Linux跑在JavaScript虚拟机上,这就是把机器模型往JavaScript模型上映射。

建立新模型肯定依赖于现有的模型,但这是建模的手段而不是目的,任何一种新模型的目的都为了更简单地分析和解决某一类问题。线性代数在建立的时候,它的各种概念和运算规则依赖于初等数学的知识,但是一旦建立起来这层抽象模型之后,我们就 应该习惯于直接利用高层次的抽象模型去分析和解决问题 。说到线性代数是为了比初等数学更容易地分析和解决问题,下面我们通过一个例子来实际感受一下它的好处:

初等数学中三角形面积最著名的计算公式是area = 1/2 base height ,当三角形有一条边恰好在坐标轴上时我们就很容易算出它的面积。但是,假如同样一个三角形我们把坐标轴旋转一下,让它的边不在坐标轴上,怎么办?我们还能得到它的底和高吗?答案肯定是可以的,但是就明显复杂了,而且还要分很多种情况去分别讨论。

相反,如果我们用线性代数知识来解决这个问题就非常轻松。在线性代数中两个向量a,b的叉积(Cross Product)是一个向量,其方向与a,b垂直,其大小等于a,b构成的平行四边形的面积:

我们可以把三角形的边视为向量,所以三角形的面积等于两个边向量的叉积向量的长度除以二:

注:length表示取向量长度,cross_product表示两个向量的叉积。

这样一个在初等数学里面有点儿小难的问题在线性代数中瞬间搞定!可能有人会说,你直接基于叉积来做,当然简单了,但是叉积本身不是也挺复杂的吗?你把它展开试试看呢?是的, 模型的作用就是把一部分复杂性隐藏到模型中 ,使得模型的使用者可以更加简单地解决问题。曾经有人质疑C++太复杂,C++之父Bjarne Stroustrup这样回答:

在特定环境下,问题的复杂性是由其本质决定的,C++把一部分的复杂性纳入了语言和标准库,目的是使得应用程序更为简单。当然,并非所有场合C++都使得问题更加简单,但是从原理上讲,C++的复杂性是有道理的。除了C++,Java、SQL、CSS等各种语言和框架莫不如是,想象一下,如果不使用数据库,动不动就自己去做数据存储和管理是多么复杂啊!这样我们就不难理解为什么线性代数要定义叉积这样奇怪的运算了,它和C++把很多常用的算法和容器纳入STL是同一道理。同样的,甚至你还可以在线性代数中定义自己想要的运算拿来复用。所以,数学一点儿不死板,它和程序一样是活活泼泼的,你理解了它的来龙去脉就能驾驭自如。说到这里,我们就顺便回答一个很常见的疑惑:

其实,和程序复用一样,线性代数定义点积、叉积和矩阵运算是因为它们的应用非常广,有很大的复用价值,可以作为我们分析和解决问题的基础。比如,很多问题都涉及到一个向量到另一个向量的投影或是求两个向量的夹角,那么就会考虑专门定义点积(Dot Product)这个运算:

点积概念的提出属于设计,有发挥创造的余地;一旦设计定了,具体公式就不能随意发挥了,必须符合逻辑,保证它映射到初等数学模型的正确性。这就像一门高级语言可以定义很多概念,什么高阶函数、闭包等等,但是它必须保证映射到底层实现时在执行产生的效果符合其定义的规范。

线性代数好在哪里?

上面说了,线性代数是一种高层次抽象模型,我们可以采用学习一门程序语言的方法去学习它的语法和语义,但是这一认识不只针对线性代数,它是对每一门数学学科通用的,可能有人会有疑问

这就问到了根本上, 线性代数的核心:向量模型 。我们在初等数学中学习的坐标系属于笛卡尔所提出的解析模型,这个模型很有用,但同时也有很大的缺点。坐标系是人为加上的虚拟参考系,但是我们要解决的问题,比如求面积,图形旋转、拉伸等应用都是和坐标系无关的,建立一个虚拟的坐标系往往无助于解决问题,刚才三角形面积的例子就是这样。

向量模型很好地克服了解析模型的缺点,如果说解析模型代表了某种“绝对性”的世界观,那么向量模型就代表了某种“相对性”的世界观,我推荐把向量模型和解析模型看作对立的两种模型。

向量模型中定义了向量和标量的概念。向量具有大小和方向,满足线性组合法则;标量是只有大小没有方向的量(注:标量的另一种更深刻的定义是在旋转变换下保持不变的量)。 向量模型的优点之一是其坐标系无关性 ,也就是相对性,它在定义向量和运算规则的时候从一开始就抛开了坐标系的束缚,不管你坐标轴怎么旋转,我都能适应,向量的线性组合、内积、叉积、线性变换等等运算全部都是坐标系无关的。注意,所谓坐标系无关性不是说就没有坐标系了,还是有的,刚才三角形例子的顶点就是用坐标表示的,只是在解决问题的时候不同的坐标系不会构成影响。用一个比喻,Java号称平台无关,不是说Java就是空中楼阁,而是说你用Java编程时底层是Linux还是Windows往往对你没有影响。

向量模型有什么好处呢?除了刚才三角形面积问题是一个例子,下面我再举一个几何的例子:

这个问题如果是要从解析几何的角度去解决几乎复杂到没法下手,除非是平面恰好是过坐标轴的特殊情况,但是如果从向量模型考虑就很简单:根据平面方程,平面的法向量(Normal Vector)是v=(a, b, c),设从平面上任意一点(x, y, z)到(x0, y0, z0)的向量为w,那么通过点积dot_product(w, v)算出w到v的投影向量p,其大小就是(x0, y0, z0)到平面ax + by + cz + d = 0的垂直距离。这里用到了向量模型的基本概念:法向量,投影向量,点积,整个问题解决过程简洁明快。

下面再给大家留一道相似的练习题(熟悉机器学习的朋友可能会发现这是线性代数在线性分类中的应用):

离开向量,下面我们要请出线性代数的另一个主角:矩阵(Matrix)。

线性代数定义了矩阵和向量、矩阵和矩阵的乘法,运算规则很复杂,用来做什么也不清楚,很多初学者都不能很好地理解,可以说矩阵是学好线性代数的拦路虎。遇到复杂的东西,往往需要先避免一头陷入细节,先从整体上把握它。其实,从程序的角度看,无论形式多么奇怪,它无非是一种语法,语法必然对应了语义,所以理解矩阵的重点在于理解其语义。矩阵的语义不止一种,在不同的环境中有不同的语义,在同一环境中也可以有不同的解读,最常见的包括:1)表示一个线性变换;2)表示列向量或行向量的集合;3)表示子矩阵的集合。

矩阵作为一个整体对应的是线性变换语义:用矩阵A乘以一个向量v得到w,矩阵A就代表了v到w的线性变换。比如,如果想要把向量v0按逆时针方向旋转60度得到v',只需要用旋转变换矩阵(Rotation Matrix)去乘v0就可以了。

除了旋转变换,拉伸变换也是一种常见的变换,比如,我们可以通过一个拉伸矩阵把向量沿x轴拉伸2倍(请试着自己给出拉伸矩阵的形式)。更重要的是,矩阵乘法有一个很好的性质:满足结合率,这就意味着 可以对线性变换进行叠加 。举个例子,我们可以把“沿逆时针旋转60度”的矩阵M和“沿x轴拉伸2倍”的矩阵N相乘,得到一个新矩阵T来代表“沿逆时针旋转60度并沿x轴拉伸2倍”。这是不是很像我们Shell中把多个命令通过管道进行叠加呢?

上面重点介绍了向量模型的坐标系无关性,除此之外, 向量模型的另一优点是它能描述线性关系 ,下面我们来看一个熟悉的Fibonacci数列的例子:

首先,我们构造两个向量v1=(f(n+1), f(n))和v2=(f(n+2), f(n+1)),根据Fibonacci数列性质,我们可以得到从v1到v2的递推变换矩阵:

并进一步得到:

这样就把线性递推问题转化为了矩阵的n次幂经典问题,在O(log n)时间复杂度内解决。除了线性递推数列,初等数学中著名的n元一次方程组问题也可以转化为矩阵和向量乘法形式更容易地解决。这个例子是想说明,凡是满足线性关系的系统都是向量模型的用武之地,我们往往可以把它转化为线性代数得到简洁高效的解决方案。

总结

本文提出了一种观点:从应用的角度,我们可以把线性代数视为一门特定领域的程序语言。线性代数在初等数学基础上建立了向量模型,定义了一套语法和语义,符合程序语言的语言契约。向量模型具有坐标系无关性和线性性,它是整个线性代数的核心,是解决线性空间问题的最佳模型。向量的概念、性质、关系、变换是掌握和运用线性代数的重点。

所谓地址映射,就是将芯片上的存储器 甚至I/O等资源与地址建立一一对应的关系。如果某地址对应着某寄存器,我们就可以运用c语言的指针来寻址并修改这个地址上的内容,从而实现修改该寄存器的内容。

内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程 *** 作文件,就像 *** 作进程空间里的地址一样了,比如使用c语言的

memcpy等内存 *** 作的函数。这种方法能够很好的应用在需要频繁处理一个文件或者是一个大文件的场合,这种方式处理IO效率比普通IO效率要高

共享内存是内存映射文件的一种特殊情况,内存映射的是一块内存,而非磁盘上的文件。共享内存的主语是进程(Process), *** 作系统默认会给每一

个进程分配一个内存空间,每一个进程只允许访问 *** 作系统分配给它的哪一段内存,而不能访问其他进程的。而有时候需要在不同进程之间访问同一段内存,怎么办

呢? *** 作系统给出了创建访问共享内存的API,需要共享内存的进程可以通过这一组定义好的API来访问多个进程之间共有的内存,各个进程访问这一段内存就

像访问一个硬盘上的文件一样。而Net 40中引入了SystemIO

MemoryMappedFiles命名空间,这个命名空间的类对windows

共享内存相关API做了封装,使Net程序员可以更方便的使用内存映射文件。

在C#中使用共享内存。以下App1的代码让用户输入一行文本到共享内存中;App2不停的刷新控制台,输出最新的共享内存内容;App3实现的功能和App2相同,但读取方法不同。

App1代码:

using System;

using SystemCollectionsGeneric;android从资源文件中读取文件流显示

using SystemLinq;

using SystemText;

using SystemIO;

//引用内存映射文件命名空间

using SystemIOMemoryMappedFiles;

namespace App1

{

class Program

{

static void Main(string[] args)

{

long capacity = 1<<10<<10;

//创建或者打开共享内存

using (var mmf = MemoryMappedFileCreateOrOpen("testMmf", capacity, MemoryMappedFileAccessReadWrite))

{

//通过MemoryMappedFile的CreateViewAccssor方法获得共享内存的访问器

var viewAccessor = mmfCreateViewAccessor(0, capacity);

//循环写入,使在这个进程中可以向共享内存中写入不同的字符串值

while (true)

{

ConsoleWriteLine("请输入一行要写入共享内存的文字:");

string input = ConsoleReadLine();

//向共享内存开始位置写入字符串的长度

viewAccessorWrite(0, inputLength);

//向共享内存4位置写入字符

viewAccessorWriteArray<char>(4, inputToArray(), 0, inputLength);

}

}

}

}

}

App2代码:

using System;

using SystemCollectionsGeneric;

using SystemLinq;

using SystemText;

using SystemThreading;

//引用使用内存映射文件需要的命名空间

using SystemIOMemoryMappedFiles;

namespace App2

{

class Program

{

static void Main(string[] args)

{

long capacity = 1<<10<<10;

using (var mmf = MemoryMappedFileOpenExisting("testMmf"))

{

MemoryMappedViewAccessor viewAccessor = mmfCreateViewAccessor(0, capacity);

//循环刷新共享内存字符串的值

while (true)

{

//读取字符长度

int strLength = viewAccessorReadInt32(0);

char[] charsInMMf = new char[strLength];

//读取字符

viewAccessorReadArray<char>(4, charsInMMf, 0, strLength);

ConsoleClear();

ConsoleWrite(charsInMMf);

ConsoleWrite("\r");

ThreadSleep(200);

}

}

}

}

}

App3代码:

using System;

using SystemCollectionsGeneric;

using SystemLinq;

using SystemText;

using SystemIOMemoryMappedFiles;

using SystemIO;

namespace App3

{

class Program

{

static void Main(string[] args)

{

long capacity = 1 << 10 << 10;

//打开共享内存

using (var mmf = MemoryMappedFileOpenExisting("testMmf"))

{

//使用CreateViewStream方法返回stream实例

using (var mmViewStream = mmfCreateViewStream(0, capacity))

{

//这里要制定Unicode编码否则会出问题

using (BinaryReader rdr = new BinaryReader(mmViewStream,EncodingUnicode))

{

while (true)

{

mmViewStreamSeek(0, SeekOriginBegin);

int length = rdrReadInt32();

char[] chars = rdrReadChars(length);

ConsoleWrite(chars);

ConsoleWrite("\r");

SystemThreadingThreadSleep(200);

ConsoleClear();

}

}

}

}

}

}

}

人,是感官的动物。

我们的大脑,像一块复杂度极高的CPU,每天在接收着各种格式的数据,进行着无休止的计算。我们以各种感官接触着这个世界,抽取着不同感官下的信息,从而认知了世界。而图像作为承载信息最为丰富的一种媒介,在人类探索智慧的历史中,一直占据着重要的位置。人用这样一双肉眼如何识别不同类别的图像(image classification and pattern recognition),如何在图像中分割出形形色色的物体(semantic segmentation and object detection),如何从模糊的图像中想象出物体的轮廓(image super-resolution),如何创作出天马行空的图画(image synthesis),都是目前 机器视觉图像处理领域 关注的热点问题。全世界的研究者都希望有朝一日,计算机能代替人眼来识别这一幅幅图像,发现在图像中隐藏的密码。

图像分类是图像处理中的一个重要任务 。在传统机器学习领域,去识别分类一个一个图像的标准流程是特征提取、特征筛选,最后将特征向量输入合适的分类器完成特征分类。直到2012年Alex Krizhevsky突破性的提出AlexNet的网络结构, 借助深度学习的算法,将图像特征的提取、筛选和分类三个模块集成于一体 ,设计5层卷积层加3层全连接层的深度卷积神经网络结构,逐层对图像信息进行不同方向的挖掘提取,譬如浅层卷积通常获取的是图像边缘等通用特征,深层卷积获取的一般是特定数据集的特定分布特征。AlexNet以154%的创纪录低失误率夺得2012年ILSVRC(ImageNet大规模视觉识别挑战赛)的年度冠军,值得一提的是当年亚军得主的错误率为262%。 AlexNet超越传统机器学习的完美一役被公认为是深度学习领域里程碑式的历史事件,一举吹响了深度学习在计算机领域爆炸发展的号角 。

时间转眼来到了2014年,GoogleNet横空出世,此时的深度学习,已经历ZF-net,VGG-net的进一步精炼,在网络的深度,卷积核的尺寸,反向传播中梯度消失问题等技术细节部分已有了详细的讨论,Google在这些技术基础上引入了Inception单元,大破了传统深度神经网络各计算单元之间依次排列,即卷积层->激活层->池化层->下一卷积层的范式,将ImageNet分类错误率提高到了67%的高水平。

在网络越来越深,网络结构越来越复杂的趋势下,深度神经网络的训练越来越难,2015年Microsoft大神何恺明(现就职于Facebook AI Research)为了解决训练中准确率先饱和后降低的问题,将residual learning的概念引入深度学习领域,其核心思想是当神经网络在某一层达到饱和时,利用接下来的所有层去映射一个f(x)=x的函数,由于激活层中非线性部分的存在,这一目标几乎是不可能实现的。

但ResNet中,将一部分卷积层短接,则当训练饱和时,接下来的所有层的目标变成了映射一个f(x)=0的函数,为了达到这一目标,只需要训练过程中,各训练变量值收敛至0即可。Resdiual learning的出现,加深网络深度提高模型表现的前提下保证了网络训练的稳定性。2015年,ResNet也以36%的超低错误率获得了2015年ImageNet挑战赛的冠军,这一技术也超越了人类的平均识别水平,意味着人工智能在人类舞台中崛起的开始。

图像分类任务的实现可以让我们粗略的知道图像中包含了什么类型的物体,但并不知道物体在图像中哪一个位置,也不知道物体的具体信息,在一些具体的应用场景比如车牌识别、交通违章检测、人脸识别、运动捕捉,单纯的图像分类就不能完全满足我们的需求了。

这时候,需要引入图像领域另一个重要任务: 物体的检测与识别 。在传统机器领域,一个典型的案例是利用HOG(Histogram of Gradient)特征来生成各种物体相应的“滤波器”, HOG滤波器 能完整的记录物体的边缘和轮廓信息,利用这一滤波器过滤不同的不同位置,当输出响应值幅度超过一定阈值,就认为滤波器和中的物体匹配程度较高,从而完成了物体的检测。这一项工作由Pedro F Felzenszalb,Ross B Girshick,David Mcallester还有Deva Ramanan以Object Detection with Discriminatively Trained Part-Based Models共同发表在2010年9月的IEEE Transactions on Pattern Analysis and Machine Interlligence期刊上。

时间如白驹过隙,惊鸿一瞥,四年过去,Ross B Girishick已由当年站在巨人肩膀上的IEEE Student Member成长为了AI行业内独当一面的神级人物,继承了深度学习先驱的意志,在2014年CVPR会议上发表题为Rich Feature Hirarchies for Accurate Object Detection and Semantic Segmentation文章。RCNN,一时无两,天下皆知。

RCNN 的核心思想在于将一个物体检测任务转化为分类任务 ,RCNN的输入为一系列利用selective search算法从图像中抽取的图像块,我们称之为region proposal。经过warping处理,region proposals被标准化到相同的尺寸大小,输入到预先训练好并精细调参的卷积神经网络中,提取CNN特征。得到了每一个proposal的CNN特征后,针对每一个物体类别,训练一个二分类器,判断该proposal是否属于该物体类别。2015年,为了缩短提取每一个proposal的CNN特征的时间,Girishick借鉴了Spatial Pooling Pyramid Network(SPPnet)中的pooling技术,首先利用一整幅图像提取CNN特征图谱,再在这张特征图谱上截取不同的位置的proposal,从而得到不同尺寸的feature proposals,最后将这些feature proposals通过SPPnet标准化到相同的尺寸,进行分类。这种改进,解决了RCNN中每一个proposal都需要进行CNN特征抽取的弊端,一次性在整图上完成特征提取,极大的缩短了模型的运行时间,因而被称作“Fast R-CNN”,同名文章发表于ICCV 2015会议。

2015年,Girishick大神持续发力,定义RPN(region-proposal-network)层,取代传统的region proposal截取算法,将region proposal的截取嵌入深度神经网络中,进一步提高了fast R-CNN的模型效率,因而被称作“Faster R-CNN”,在NIPS2015上Girishick发表了题为“Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks”的关键文章,完成了RCNN研究领域的三级跳壮举。

随着时代的发展, 科学家们不仅仅是技术的研究者,更是艺术的创造者 。

在人工智能领域的另一位新一代灵魂人物,Ian Goodfellow在2014年提出了Generative Adversarial Net的概念,通过定义一个生成器(generator)和一个判别器(discriminator)来完成图像生成任务。其原理在于生成器的任务是从随机噪声中“创造”出接近目标图像的“假图像”去欺骗判别器,而判别器的任务是去甄别哪一些图像是来自于真实的数据集,哪一些图像是来自于生成器,在生成器和判别器的互相对抗中,通过合理的损失函数设计完成训练,最终模型收敛后,判别器的概率输出为常数05,即一幅图像来自于生成器和真实数据集的概率相同,生成器生成的图像的概率分布无限趋近于真实数据集。

GAN技术成为2015,2016年深度学习研究的热门领域,在图像恢复、降噪、超分辨重建等方向获得了极佳的表现,衍生出一系列诸如WGAN,Info-GAN,DCGAN,Conditional-GAN等技术,引领了一波风潮。

当我们把一帧帧图像串联在一起,变成流动的光影,我们研究的问题就从空间维度上扩展到了时间维度,我们不仅需要关心物体在图像中的位置、类别、轮廓形状、语义信息,我们更要关心图像帧与帧之间的时间关系,去捕捉、识别一个物体的运动,去提取视频的摘要,去分析视频所表达的含义,去考虑除了图像之外的声音、文本标注,去处理一系列的自然语言,我们的研究一步一步,迈向了更广阔的星辰与大海。

图像和视频,都是虚拟的一串串数字,一个个字节,但却让这个世界更加真实 。

   

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/9292554.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-26
下一篇2023-04-26

发表评论

登录后才能评论

评论列表(0条)

    保存