秋招在即,你準備好了嗎?BAT算法工程師面試經驗分享。

本文 GitHub https://github.com/Jack-Cherish/PythonPark 已收錄,有技術乾貨文章,整理的學習資料,一線大廠面試經驗分享等,歡迎 Star 和 完善。

一、前言

2020 年,魔幻開局。

全球疫情、美國暴亂、印度蝗災,天災人禍接踵不斷。

學生們沒想到,一個寒假,竟然可以放到暑假。

"社畜們"也沒想到,遠程辦公,竟然如此酸爽。

時間,不知不覺中,已經來到了 7 月。

恍然發現,2020 年已經悄然過去了一半。

秋天還沒到,互聯網公司的秋招提前批已悄然來襲。

秋招在即,你準備好了嗎?

無論是學生黨要找實習、找工作,還是工作黨要跳槽、要轉崗。

秋招,都是一個必須把握的機會。

想要找個好工作,都要準備哪些?

回憶自己的秋招,在此分享一些面試經驗

二、經驗總結

想要找個好工作,都要準備些什麼?

最好地瞭解一個工作崗位需求的方法,就是看 JD(job description)。

比如騰訊的一個視覺算法崗位,這樣寫着:

根據 JD 上的描述,可以有針對性地做一些準備。

其他崗位,也是如此,需要準備什麼,一目瞭然。

本文就以我當初秋招找實習、找工作爲例,分享一下我的算法面經

我選擇崗位的標準是,找各個公司最適合我的崗位,有就投,沒有就 pass,因此我投遞的崗位有些多樣,主要投遞的崗位:算法工程師、機器學習/深度學習工程師、數據挖掘工程師。

參加過的面試形式有:電話面、視頻面、現場面。

對了,找工作期間,如果你的電話來電有房產中介之類的標識,也要接起來,不要直接掛斷,因爲這沒準就是你面試官的副業(尷尬臉)。

1、認真思考

對於學生,剛開始參加面試,往往不夠自信。例如我第一次參加遠程電話面試的時候,面對面試官的問題,我的第一反應是這個問題在哪看過,網上是怎麼說的,甚至是在哪能找到答案。

當時的我忽略了思考這個問題本身,總想着從何處能找到所謂的正確答案。

這就是準備不充分、不自信、緊張共同造成的結果。

其實,如果認真地思考問題本身,答案並不難想到。

往往掛斷電話後,自己認真思考一番,然後悔恨不已:哇,剛纔怎麼沒有想到!

所以一句話:面對面試官的問題,一定要自己認真思考問題本身,自信一些,大膽說出自己的想法,如果碰到有耐心的面試官,他會一步一步引導你。

2、做好準備

充足的準備很重要,“佛系”隨緣面試不可取。

我們需要根據崗位需求,着重準備以下幾點:自我介紹、數據結構、簡歷項目、崗位需求。

  • 自我介紹:這個是最好準備的東西了,根據自己的實際經歷,組織好語言即可。面試官一般剛開始會讓你做一個簡短的自我介紹,以便他快速瀏覽一下你的簡歷。
  • 數據結構:數據結構很重要,屬於必過的一關。至少要刷一遍劍指 offer,或者刷一遍 leetcode 的 top100 題目。面試讓寫一道編程題,這都是常規操作。
  • 簡歷項目:面試官問的一些問題往往都是針對項目經歷問的,我當初的簡歷上寫了基於嵌入式平臺的目標檢測系統,那麼面試官就會問 YOLO、SSD 的算法原理。YOLO v2 v3 v4 做出了哪些改進?針對自己簡歷上寫的項目,好好想一想可能會問哪些問題。自問自答走一波。
  • 崗位需求:這個就需要我們針對崗位要求進行準備了,比如對於深度學習崗位,會問下神經網絡基礎,卷積核是怎麼計算的?卷積層、全連階層都有什麼作用?你會用哪些深度學習框架,可以簡述下使用流程嗎?你認爲深度學習和傳統機器學習本質上有什麼不同?對於這些問題,我們都可以提前準備,面試前一個小時,好好過一遍,會有意想不到的收穫的。

3、時刻準備

有些公司的面試電話說不定什麼時候就打進來了,可能投遞簡歷半個月了,你都忘記了。

本以爲是直接約個面試時間,結果上來直接面試。

當然此時,你可以說下自己現在不方便,可不可以另約時間。

但是心裏總會有疑慮:哇,這樣做,另約時間,到時他會不會忘了?面試晚了,會不會崗位就招滿了?諸如此類的想法。

其實,大多數的時候是沒有問題的,不必有這些想法。當然,爲了完全避免這些憂慮,時刻做好面試準備,保持電話時刻暢通是很有必要的。

4、儘量內推

內推很重要,如果沒有內推,那麼需要走簡歷篩選流程,就是 HR 從簡歷池把你的簡歷撈出來,如果沒有撈出來,也就是沒有相中你的簡歷,很可能你連面試機會都沒有。

但是如果有內推,就會好很多。而且內推可以走提前批,大廠都有這些流程,意思就是不用等後面的統一筆試,直接面試。從哪找內推呢?

  • 通過師兄、師姐;
  • 招聘網站,例如針對校招的「牛客網」,還有針對校招和社招的「BOSS 直聘」等;
  • 社交 APP,比如「脈脈」、「領英」等;
  • 通過 QQ 羣,比如一些春招內推羣、秋招內推羣;
  • 通過學校的 BBS,對於外校不能訪問的 BBS ,例如「北郵人」,可以找同學借帳號,或者通過鏡像站進入;
  • 還有就是公衆號了,現在很多公衆號都在做內推方面的內容。

5、不要着急

這一點我感覺也很重要,別上來就投 BAT 大廠的崗位,先拿非理想公司的崗位,試試水,感受一下面試的氛圍。

不過話說回來,其實可能一些初創公司面試反而會更難,因爲 BAT 這些大廠出題都是有跡可循,而一些初創公司說不定考你什麼,並且可能崗位要求比大廠還高。

學會總結經驗,學會在一次次面試中成長。

6、博客、Github沒那麼重要

好的技術博客,牛的 Github 項目,不一定有加分。

這個完全是看試官怎麼看,面試官感覺好,就有用。如果面試官感覺沒用,那就作用不大。

儘管用處不是很多,但是以技術博客的形式記錄自己的所學,也有助於後續的回顧。

此外,有個好的技術博客或者 Github 項目,會有一些人主動聯繫你,幫你內推。不過,後續的面試情況還是要看你自己的發揮。

7、運氣也很重要

面試也很看運氣,與其說是運氣,不如說是面試技巧。

這個東西挺玄學的,不過它確實存在,比如面試時,問的題目剛好是自己都會的,那麼恭喜,這輪面試你就輕鬆過去了。

不能否認運氣的存在,但也不能全靠運氣,要自身實力過硬纔行。

三、問題彙總

接下來,就總結一下,我在當初面試時,被問到的一些常見問題。

問題總共可分爲七類:數學題、計算機基礎、數據結構、機器學習相關、深度學習相關、項目相關、業務場景。

項目相關的問題,根據每個人的項目經歷而不同,這個需要自行準備了,根據實際情況闡述。

本文主要記錄另外六類問題。

1、數學題

面試的時候偶爾會被問道數學題,這裏也值得準備一下,特別是算法崗。

面試的題型完全看面試官的風格,比如問問泰勒展開、偏導啥的,還有一些五花八門的小智力題。

不過這類考點,考得並不多,十場面試,可能就碰到一場問數學題的。

2、計算機基礎

計算機基礎屬於常考內容。一般都會問一些 linux 基礎,比如常用 linux 指令,平時經常用 linux 的話,這個問題不大。

如果沒有這方面基礎的,就需要提前學一學了。

此外,還會問一下關於你熟悉的計算機語言的基礎知識,比如我說我更熟悉 python ,那麼面試官可能就會問一些關於 python 基礎的問題。

常考問題如下:

1)  進程和線程的區別?

答:進程擁有一個完整的虛擬地址空間,不依賴於線程而獨立存在;反之,線程是進程的一部分,沒有自己的地址空間,與進程內的其他線程一起共享分配給該進程的所有資源。

比如:開個 QQ,開了一個進程;開了迅雷,開了一個進程。在 QQ 的這個進程裏,傳輸文字開一個線程、傳輸語音開了一個線程、彈出對話框又開了一個線程。所以運行某個軟件,相當於開了一個進程。在這個軟件運行的過程裏(在這個進程裏),多個工作支撐的完成 QQ 的運行,那麼這“多個工作”分別有一個線程。所以一個進程管着多個線程。通俗的講:“進程是爹媽,管着衆多的線程兒子”。

2)  爲什麼說 python 的線程是僞線程?

答:在 python 的原始解釋器 CPython 中存在着 GIL(Global Interpreter Lock,全局解釋器鎖),因此在解釋執行 python 代碼時,會產生互斥鎖來限制線程對共享資源的訪問,直到解釋器遇到 I/O 操作或者操作次數達到一定數目時纔會釋放 GIL 。

所以,雖然 CPython 的線程庫直接封裝了系統的原生線程,但 CPython 整體作爲一個進程,同一時間只會有一個線程在跑,其他線程則處於等待狀態。這就造成了即使在多核 CPU 中,多線程也只是做着分時切換而已。

3)  python 的 append 和 extend 有什麼區別?

答:extend() 接受一個列表參數,把參數列表的元素添加到列表的尾部,append() 接受一個對象參數,把對象添加到列表的尾部。

例如:

a = [1,2]
b = [1,2,3]
a.append(b)
print(a)

輸出結果爲:

[1, 2, [1, 2, 3]]

而:

a = [1,2]
b = [1,2,3]
a.extend(b)
print(a)

輸出結果爲:

[1, 2, 1, 2, 3]

4)  linux 下創建定時任務使用什麼指令?

答:可以使用 crontab 命令。

5)  數據庫 Mysql 和 MongoDB 的區別?

答:Mysql 是關係型數據庫,MongoDB 是文檔型數據庫。MongoDB 佔用空間大,典型的用空間換時間原則的類型。Mysql 相對成熟,MongoDB 較爲年輕。

6)  你知道的加解密算法有哪些?

答:AES(對稱加密)、RSA(非對稱加密)、MD5(Hash算法)等。

3、數據結構

個人感覺數據結構最重要,面試五花八門什麼題都有,但是唯一統一的,就是數據結構基礎。

不考數據結構的情況也有,但這種情況少之又少。

數據結構的考法,也各有不同。有的讓說思路,有的讓在線寫代碼。

所以,複習的方法應該是:審題->思考->表達->碼字。

首先,認真審題,審題很重要。然後組織語言,把自己所想表達清楚。

別小看這一步,一些公司面試都是讓先說解題思路,再寫代碼,甚至是隻需要說思路。

我這有一份當初刷題的記錄,劍指 Offer 系列的刷題筆記,解題思路+代碼都有:

已分門別類整理好,有需要的自取。

地址:https://cuijiahua.com/blog/2018/02/basis_67.html

下面對一些常見題型進行彙總,這些也是我當初面試時,真實被問到的題目以及相關擴展題。

鏈表:

1) 找出單鏈表的倒數第K個元素(僅允許遍歷一遍鏈表)

答:使用指針追趕的方法,定義一個 fast 指針和一個 slow 指針,fast 指針先走 K 步,然後 fast 和slow 同時繼續走。當 fast 指針走到鏈表尾部時,slow 指向的位置就是倒數第 K 個元素。

注意:要考慮鏈表長度應該大於 K 。參考:劍指Offer(十四):鏈表中倒數第k個結點

2) 找出單鏈表的中間元素(僅允許遍歷一遍鏈表)

答:使用指針追趕的方法,定義一個 fast 指針和一個 slow 指針,兩個指針同時走,fast 指針每次走兩步,slow 指針每次走一步。當 fast 指針到鏈表尾部時,slow 指針指向的就是鏈表的中間元素。

3) 判斷單鏈表是否有環?

答:使用指針追趕的方法,定義一個 fast 指針和一個 slow 指針,兩個指針同時走,fast 指針每次走兩步,slow 指針每次走一步。如果有環,則兩者會相遇;如果沒有環,fast 指針會遇到 NULL 退出。

4) 已知單鏈表有環,如何知道環的長度?

答:使用指針追趕的方法,定義一個 fast 指針和一個 slow 指針,兩個指針同時走,fast 指針每次走兩步,slow 指針每次走一步,找到碰撞點。然後使用 slow 指針,從該碰撞點開始遍歷,繞着走一起圈,再次回到該點,所走過的結點數就是環的長度。

5) 如何找到環的入口結點?

答:先使用題 4 的方法,計算出環的長度。然後重新從頭結點開始遍歷,定義定義一個 fast 指針和一個 slow 指針,fast 指針先走 l(環的長度)步,然後兩個指針以相同的速度在鏈表上向前移動,直到它們再次相遇,那麼這個相遇點即爲環的入口結點。

參考:劍指Offer(五十五):鏈表中環的入口結點

6) 判斷兩個無環單鏈表是否相交?

答:一旦兩個鏈表相交,那麼兩個鏈表從相交節點開始到尾節點一定都是相同的節點。所以,如果他們相交的話,那麼他們最後的一個節點一定是相同的,因此分別遍歷到兩個鏈表的尾部,然後判斷他們是否相同。

7) 如何知道兩個單鏈表(可能有環)是否相交?

答:根據兩個鏈表是否有環來分別處理,若相交這個環屬於兩個鏈表共有

(1)如果兩個鏈表都沒有環,如題 6 所示方法。

(2)一個有環,一個沒環,肯定不相交。

(3)兩個都有環。在 A 鏈表上,使用指針追趕的方法,找到兩個指針碰撞點,之後判斷碰撞點是否在 B 鏈表上。如果在,則相交。

8) 尋找兩個相交鏈表的第一個公共結點。

答:我們也可以先讓把長的鏈表的頭砍掉,讓兩個鏈表長度相同,這樣,同時遍歷也能找到公共結點。此時,時間複雜度 O(m+n),空間複雜度爲 O(MAX(m,n)) 。

參考:劍指Offer(三十六):兩個鏈表的第一個公共結點

9) 反轉鏈表。

答:我們使用三個指針,分別指向當前遍歷到的結點、它的前一個結點以及後一個結點。在遍歷的時候,交換當前結點的尾結點和前一個結點的。

參考:劍指Offer(十五):反轉鏈表指

數組:

1) 給定一個數組(非遞減排序),同時給定一個目標數字,找出這個數字在該數組中第一次出現的位置,如果不存在,返回-1。例如[1,3,5,5,5,5,8,9,13,15],輸入5,返回2,輸入8,返回6,輸入18,返回-1。

答:使用二分查找法即可。

# -*-coding:utf-8 -*-
def BinarySearch(input_list, end, value):
	if end == 0 or value < input_list[0] or value > input_list[-1]:
		return -1
	left = 0
	right = end - 1
	while left <= right:
		middle = left + (right - left) // 2
		if input_list[middle] >= value:
			right = middle - 1
		else:
			left = middle + 1
 
	return left if left < end else -1

if __name__ == '__main__':
	input_list = [1,3,5,5,5,5,8,9,13,15]
	target = 5
	print(BinarySearch(input_list, len(input_list), target))

運行結果如下圖所示:

秋招在即,你準備好了嗎?

2) 給定一個數組,裏面有很多數字(亂序),找出其中最大的 4 個數字。

答:最簡單的辦法就是先排序再找出最大的四數,這種方法時間複雜度過高。一個更好的方法是使用堆排序,即維護一個存儲最大的4個數的最小堆。

解析:這的思想和代碼可以參考《劍指Offer(二十九):最小的K個數》,這裏僅僅做了一個變形。

3) 給定一個整數的數組 nums,返回相加爲 target 的兩個數字的索引值。假設每次輸入都只有一個答案,並且不會使用同一個元素兩次。

答:如果這個數組是已經排序的,可以使用頭指針和尾指針,我們可以定義一個頭指針 left,一個尾指針 right 。left 指針指向元素值+ right 指針指向元素值的和爲 sum,用 sum 和 target 比較。如果sum > target,說明和大了,那麼 right 右指針左移一位,然後重新判斷。反之,如果 sum < target,說明和小了,那麼 left 左指針右移以爲,然後會從新判斷。直到找到 sum=target 的情況。如果沒有排序,可以使用使用哈希表,也就是散列表。

解析:如果沒有排序,這道題就是Leetcode中的一道題。代碼可以參考《Two Sum》。

4) 給定一個字符串,找到最長無重複子字符串。

答:定義兩個變量 longest 和 left ,longest 用於存儲最長子字符串的長度,left 存儲無重複子串左邊的起始位置。然後創建一個哈希表,遍歷整個字符串,如果字符串沒有在哈希表中出現,說明沒有遇到過該字符,則此時計算最長無重複子串,當哈希表中的值小於 left,說明 left 位置更新了,需要重新計算最長無重複子串。每次在哈希表中將當前字符串對應的賦值加 1 。

解析:Leetcode中的一道題。代碼可以參考《Longest Substring Without Repeating Characters》。

二叉樹:

1) 給定任意一棵二叉樹,假設每個結點之間的距離相等,現從任意葉結點,點燃這顆二叉樹,假設結點到結點間的燃燒時間均爲 1s,問需要多久能燒完整顆二叉樹。

答:二叉樹燃燒,需要向父結點遍歷。此外,因爲是燃燒整顆二叉樹,所以結點間應該是擴散式的同時燃燒。因此思路是找到點燃的葉結點到另一個結點的最大距離。

其他:

1) 不使用現成的開根號庫函數,如何實現開平方根的操作?

答:可以使用二分查找法或者牛頓法。

# -*-coding:utf-8 -*-
def sqrt_binary_search(target):
	left = 0
	right = target
	mid = (left + right) / 2

	while abs(mid*mid-target) > 0.000001:
		if mid*mid == target:
			return mid
		elif mid*mid > target:
			right = mid
		else:
			left = mid
		mid = (left + right) / 2
	return mid

def sqrt_newton(target):
	k = target
	while abs(k*k-target) > 0.000001:
		k = 0.5*(k+target/k)
	return k

if __name__ == '__main__':
	print("二分查找法:",sqrt_binary_search(64))
	print("牛頓法:",sqrt_newton(64))

運行結果如下圖所示:

2) 一個自然序列,從0開始,去掉凡是出現8和9的數,請問去掉後的序列中的第2018個數是多少?

答:這道題只要理解題意就好了,怎奈我當時緊張,感覺答的不好,其實事後仔細一想還是蠻簡單的。例如去掉後的序列爲:0,1,2,3,4,5,6,7,10,11,12,13,14,15,16,17,20,21,22,23,24,25,26,27,30,31,32,33,34,35,36,37···。通過數字規律,會發現,其實這個就是10進制轉8進制,第9個數是10,第17個數是20,第25個數是30。那麼,第2018個數是多少?用除八取餘法,得3742。而第2018個數,應該是3742-1=3741。

3) EXCEL中,列序是有規律的。A,B,C···,Z,接着是AA,AB,···,AZ,再接着是BA,BB,···,BZ。這樣一直循環下去,等到有三位的時候就是從AAA開始。請問,第2018個數對應的序列號是多少?

答:這道題還是進制轉換問題,是10進制轉26進制。比如第27個數:27除以26爲1餘1,那麼結果就是AA,第53個數:53除以26爲2餘1,那麼結果就是BA。同理,第2018個數:使用除26取餘法,得到最終結果爲BYP。

4、機器學習

1) 什麼是歸一化,歸一化的作用是什麼?

答:歸一化是將數據變爲(0,1)之間的小數,主要是爲了數據處理方便,把數據映射到0~1範圍之內處理,處理起來可以更加便捷快速。歸一化的作用是把有量綱表達式變爲無量綱表達式,歸一化是一種簡化計算的方式,即將有量綱的表達式,經過變化,化爲無量綱的表達式,成爲純量。同時,提高迭代求解的收斂速度,提高迭代求解的精度。

相應擴展:

深度學習中的歸一化應該怎麼理解?

答:神經網絡學習過程的本質是爲了學習數據分佈,一旦訓練數據與測試數據的分佈不同,那麼網絡的泛化能力也大大降低;另一方面,一旦每批訓練數據的分佈各不相同,那麼網絡就要在每次迭代都去學習適應不同的分佈,這樣會大大降低網絡的訓練速度,這也正是爲什麼我們需要對數據進行歸一化處理的原因。對於深度網絡的訓練是一個複雜的過程,只要網絡的前面幾層發生微小的改變,那麼後面幾層就會被累積放大下去。一旦網絡某一層的輸入數據的分佈發生改變,那麼這一層網絡就需要去適應學習這個新的數據分佈,所以如果訓練過程中,訓練數據的分佈一直在發生變化,那麼將會影響網絡的訓練速度。因此,我們一般會對輸入數據進行"白化"除理,使得它的均值是0,方差是1。

2) 標準化是什麼?

答:數據的標準化是將數據按比例縮放,使之落入一個小的特定區間。由於信用指標體系的各個指標度量單位是不同的,爲了能夠將指標參與評價計算,需要對指標進行規範化處理,通過函數變化將其數值映射到某個數值區間。

相應擴展:

常見的數據歸一化方法有哪些?

答:min-max標準化、z-score標準化等。

對於數據標準化/歸一化的詳細內容,可以參見:

https://blog.csdn.net/pipisorry/article/details/52247379

3) 你最熟悉的機器學習算法是什麼?可以講解下SVM原理嗎?

答:省略若干字。

解析:這部分內容可以參考我的文章《機器學習實戰教程(八):支持向量機原理篇之手撕線性SVM》,我當時面試的時候是先說的線性可分的情況,然後再引入核函數。

4) 在推導公式的時候,要向量化,這是什麼意思?

答:其實就是將多組數據,放到一個矩陣裏,進行矩陣運算。因爲如果是一條一條遍歷計算參數,需要用到for循環,這樣很浪費時間。python的第三方庫提供了很好的矩陣計算支持,我們完全可以把多組數據放到一個矩陣裏,這樣可以實現多組數據同時計算。這個向量化推導,就是根據一條數據計算公式推導出矩陣運算公式,這樣可以方便我們寫代碼。

5) 在邏輯迴歸中,我們使用的是sigmoid函數,知道sigmoid函數吧?

答:知道。

繼續問:那麼tanh函數和它有什麼區別呢?

答:它們的值域不同,sigmoid函數將輸出映射到0~1的範圍內,而tanh函數將輸出映射到-1~1的範圍內。同時,它們過零點的值也不同,sigmoid函數的過零點的值爲0.5,tanh函數過零點的值爲0。當我們更偏向於當激活函數的輸入是0時,輸出也是0的函數時候,就需要使用tanh函數,而非sigmoid函數。

6) SVM和Logistic的區別?

答:(1)SVM不是概率輸出,Logistic Regression是概率輸出。也就是說,當一個新樣本來了,SVM只會告訴你它的分類,而Logistic Regression會告訴你它屬於某類的概率!(2)異常點的魯棒性問題。當訓練樣本中存在異常點時,由於Logistic Regression的lost function中有每一個點的貢獻,所以某種程度上“削弱了”異常點的貢獻。而SVM只需要考慮支持向量,此時支持向量本來就不是很多的情況下,幾個異常點就很有可能極大影響SVM的表現。(3)目標函數不同。Logistic Regression使用cross entropy loss,互熵損失。而SVM使用hinge loss,鉸鏈損失。(4)實際問題中,如果數據量非常大,特徵維度很高,使用SVM搞不定時,還是用Logistic Regression吧,速度更快一些。

7) 常見的損失函數有哪些?

  • 鉸鏈損失(Hinge Loss):主要用於支持向量機(SVM) 中;
  • 互熵損失 (Cross Entropy Loss,Softmax Loss ):用於Logistic 迴歸與Softmax 分類中;
  • 平方損失(Square Loss):主要是最小二乘法(OLS)中;
  • 指數損失(Exponential Loss) :主要用於Adaboost 集成學習算法中;
  • 其他損失(如0-1損失,絕對值損失)。

參考鏈接:https://blog.csdn.net/u010976453/article/details/78488279

8) GBDT和XGBOOST的區別有哪些?

  • 傳統GBDT以CART作爲基分類器,xgboost還支持線性分類器,這個時候xgboost相當於帶L1和L2正則化項的邏輯斯蒂迴歸(分類問題)或者線性迴歸(迴歸問題)。
  • 傳統GBDT在優化時只用到一階導數信息,xgboost則對代價函數進行了二階泰勒展開,同時用到了一階和二階導數。順便提一下,xgboost工具支持自定義代價函數,只要函數可一階和二階求導。
  • xgboost在代價函數里加入了正則項,用於控制模型的複雜度。正則項裏包含了樹的葉子節點個數、每個葉子節點上輸出的score的L2模的平方和。從Bias-variance tradeoff角度來講,正則項降低了模型的variance,使學習出來的模型更加簡單,防止過擬合,這也是xgboost優於傳統GBDT的一個特性。
  • Shrinkage(縮減),相當於學習速率(xgboost中的eta)。xgboost在進行完一次迭代後,會將葉子節點的權重乘上該係數,主要是爲了削弱每棵樹的影響,讓後面有更大的學習空間。實際應用中,一般把eta設置得小一點,然後迭代次數設置得大一點。(補充:傳統GBDT的實現也有學習速率)
  • 列抽樣(column subsampling)。xgboost借鑑了隨機森林的做法,支持列抽樣,不僅能降低過擬合,還能減少計算,這也是xgboost異於傳統gbdt的一個特性。
  • 對缺失值的處理。對於特徵的值有缺失的樣本,xgboost可以自動學習出它的分裂方向。
  • xgboost工具支持並行。boosting不是一種串行的結構嗎?怎麼並行的?注意xgboost的並行不是tree粒度的並行,xgboost也是一次迭代完才能進行下一次迭代的(第t次迭代的代價函數裏包含了前面t-1次迭代的預測值)。xgboost的並行是在特徵粒度上的。我們知道,決策樹的學習最耗時的一個步驟就是對特徵的值進行排序(因爲要確定最佳分割點),xgboost在訓練之前,預先對數據進行了排序,然後保存爲block結構,後面的迭代中重複地使用這個結構,大大減小計算量。這個block結構也使得並行成爲了可能,在進行節點的分裂時,需要計算每個特徵的增益,最終選增益最大的那個特徵去做分裂,那麼各個特徵的增益計算就可以開多線程進行。
  • 可並行的近似直方圖算法。樹節點在進行分裂時,我們需要計算每個特徵的每個分割點對應的增益,即用貪心法枚舉所有可能的分割點。當數據無法一次載入內存或者在分佈式情況下,貪心算法效率就會變得很低,所以xgboost還提出了一種可並行的近似直方圖算法,用於高效地生成候選的分割點。

參考自:https://www.zhihu.com/question/41354392

5、深度學習

目標檢測算法相關:

1) 簡述下 YOLO 算法原理?

答:Yolo算法採用一個單獨的CNN模型實現end-to-end的目標檢測,模型參考自GoogleNet,YOLO的CNN網絡將輸入的圖片分割成SxS的網絡,然後每個單元格負責去檢測那些中心點落在該格子內的目標。每個單元格會預測B個邊界框(bounding box)以及邊界框的置信度(confidence score)。所謂置信度其實包含兩個方面,一是這個邊界框含有目標的可能性大小,二是這個邊界框的準確度,邊界框的準確度可以用預測框與實際框(ground truth)的IOU(intersection over union,交併比)來表徵。邊界框的大小與位置可以用4個值來表徵:(x,y,w,h),其中(x,y)是邊界框的中心座標,而(w,h)是邊界框的寬與高。還有一點要注意,中心座標的預測值(x,y)是相對於每個單元格左上角座標點的偏移值,並且單位是相對於單元格大小的,而(w,h)預測值是相對於整個圖片的寬與高的比例。這樣,每個邊界框的預測值實際上包含5個元素:(x,y,w,h,c),其中前4個表徵邊界框的大小與位置,而最後一個值是置信度。每個單元格需要預測 (B*5+C) 個值。如果將輸入圖片劃分爲 S*S 網格,那麼最終預測值爲 S*S*(B*5+C) 大小的張量。對於PASCAL VOC數據,其共有20個類別,如果使用 S=7,B=2 ,那麼最終的預測結果就是 7*7*30大小的張量。

2) 相對於YOLO,YOLO v2有哪些改進?

  • 首先,將dropout層去掉,在每個卷積層添加了Batch Normalization,mAP提高了2%;
  • 其次,使用高分辨率分類器,將輸入分辨率數據有224*224變爲448*448,mAP提高了4%;
  • 第三,引入anchor boxes來預測bounding boxes,去掉網絡中的全連接層。準確率只有小幅度的下降,而召回率則提升了7%,說明可以通過進一步的工作來加強準確率,的確有改進空間;
  • 第四,使用維度聚類,本文使用K-means聚類方法訓練bounding boxes,可以自行找到更好的boxes寬高維度;同時使用直接位置預測(Direct lacation prediction),將定位預測值歸一化,使參數更容易得到學習,模型更加穩定。作者使用Dimension Clusters和Direct location prediction這兩項anchor boxes改進方法,mAP獲得了5%的提升。
  • 第五,增加細粒度特徵(Fine-Grained Feature),是模型獲得多尺度的適應性,簡單添加了一個轉移層( passthrough layer),這一層要把淺層特徵圖(分辨率爲26 * 26,是底層分辨率4倍)連接到深層特徵圖。這樣做相當於做了一次特徵融合,有利於檢測小目標。
  • 最後,多尺度訓練(Multi-Scale Training),方法就是幾次迭代之後就會微調網絡,每過10次訓練(10 epoch),就會隨機選擇新的圖片尺寸。YOLO網絡使用的降採樣參數爲32,那麼就使用32的倍數進行尺度池化{320,352,…,608}。最終最小的尺寸爲320 * 320,最大的尺寸爲608 * 608。接着按照輸入尺寸調整網絡進行訓練。這種機制使得網絡可以更好地預測不同尺寸的圖片,意味着同一個網絡可以進行不同分辨率的檢測任務,在小尺寸圖片上YOLOv2運行更快,在速度和精度上達到了平衡。

3) 深度學習方法與傳統機器學習方法的區別是什麼?

答:機器學習包括深度學習,深度學習是使用卷積層學習特徵,而非像機器學習那樣需要人爲提取特徵,深度學習可以自行學習到更深層次的特徵。機器學習方法的各個公式有數學理論推導支持,深度學習方法就像一個黑匣子,缺少數學理論支持。

4) YOLO的損失函數是什麼?

答:YOLO算法將目標檢測看成迴歸問題,採用的是均方差損失函數。公式如下圖所示:

6、業務場景

種這題目也是常出題目,會給定你一個場景來提問。

1)  如果給了你很多數據,這些數據已經標註好,即已經做好分類,現在讓你訓練出一個模型,用於區分新來的數據屬於哪一類,你需要怎麼做呢?可以說下詳細的流程嗎?

答:首先這是一個分類問題,首先應該想到的是可以嘗試使用常用的分類算法,例如樸素貝葉斯、決策樹或者SVM。拿到數據之後,做的第一件事就是特徵工程。然後將數據分類兩部分,一部分用於訓練,另一部分用於測試,即分爲訓練集和測試集,不混用。其實,使用什麼分類算法倒是其次,重要在於選好特徵,對於給定的特徵,需要做一些過濾,比如一些干擾數據,如果對於結果影響很大,可以嘗試捨棄這些數據。除此之外,看看是否需要對數據進行歸一化處理,將數據無量綱化。然後對已經處理好的特徵,送入分類算法中,讓其學習。最後,可以通過查看測試集的預測準確度,對一些算法必要參數進行優化調試。

解析:我當時差不多就是這麼回答的,只要有的說,讓面試官認爲你做過相關工作即可。

2) 如果給你1億個數據,讓你找出其中第 1000 大的數據,你會怎麼做?我們先不考慮多進程和多線程,也不考慮數據庫,如何在算法方面給出思路呢?

答:可以使用堆排序,創建一個存儲1000個數據的小根堆。先將1億個數據的前1000個數據放入這個小根堆中,然後繼續遍歷,對於新插入的數據,需要與小根堆的最小值進行比較,如果待插入的數據比這個最小值還小,那麼不插入,如果比這個最小值大,那麼就插入該數,並重新調整小根堆,隨後繼續使用此方法遍歷整個數據。遍歷一次數據後,就得到了前1000大的數據,然後輸出小根堆的最小值,即根值,即可得到第1000大的數據。

PS:還有一種思路,有就是利用 MapReduce,實際工作中,非常常用的工具。

四、總結

  • 本文總結的題目,都是我當初剛參加工作面試遇到的一些常規題目,例如 YOLO 系列算法,現在已經出了 YOLO v3、YOLO v4 ,有新算法就得看,需要跟進最新的進展。
  • 臨陣磨槍,不快也光。面試前,看一看自己的筆記,沒準面試的時候正好碰到。
  • 好好準備,祝在座的各位,人人都是 offer 收割機。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章