2021年6月9日,CVTE NLP算法崗面試題9道

1.講一下改進的tf-idf

TF-IDF中的IDF是一種試圖抑制噪聲的加權,單純的覺得文本頻率小的單詞就越重要,文本頻率越大的單詞就越無用,這一方式會在同類語料庫中存在巨大弊端,一些同類文本的關鍵詞容易被掩蓋。例如:語料庫 D 中教育類文章偏多,而文本 j 是一篇屬於教育類的文化在那個,那麼教育類相關詞語的IDF值就會較小,使提取本文關鍵詞的召回率更低。python

改進方法:TF−IWF (Term Frequency-Inverse Word Frequency)git

AI充電季,開寶箱免費學正價課!

更有200本紙質書等,來就送!>>>AI充電季,開寶箱免費學正價課,200本紙質書等包郵送!-七月在線算法

2.講一下k-means與譜聚類

聚類算法屬於無監督的機器學習算法,即沒有類別標籤y,須要根據數據特徵將類似的數據分爲一組。K-means聚類算法即隨機選取k個點做爲聚類中心,計算其餘點與中心點的距離,選擇距離最近的中心並歸類,歸類完成後計算每類的新中心點,從新計算每一個點與中心點的聚類並選擇距離最近的歸類,重複此過程,直到中心點再也不變化。markdown

譜聚類的思想是將樣本看做頂點,樣本間的類似度看做帶權的邊,從而將聚類問題轉爲圖分割問題:找到一種圖分割的方法使得鏈接不一樣組的邊的權重儘量低(這意味着組間類似度要儘量低),組內的邊的權重儘量高(這意味着組內類似度要儘量高),從而達到聚類的目的。網絡

3.蒸餾的思想,爲何要蒸餾?

知識蒸餾就是將已經訓練好的模型包含的知識,蒸餾到另外一個模型中去。具體來講,知識蒸餾,能夠將一個網絡的知識轉移到另外一個網絡,兩個網絡能夠是同構或者異構。作法是先訓練一個teacher網絡,而後使用這個teacher網絡的輸出和數據的真實標籤去訓練student網絡。app

在訓練過程當中,咱們須要使用複雜的模型,大量的計算資源,以便從很是大、高度冗餘的數據集中提取出信息。在實驗中,效果最好的模型每每規模很大,甚至由多個模型集成獲得。而大模型不方便部署到服務中去,常見的瓶頸以下:機器學習

  • 推斷速度慢
  • 對部署資源要求高(內存,顯存等),在部署時,咱們對延遲以及計算資源都有着嚴格的限制。

所以,模型壓縮(在保證性能的前提下減小模型的參數量)成爲了一個重要的問題。而」模型蒸餾「屬於模型壓縮的一種方法。oop

4.有哪些蒸餾方式? 蒸餾中的學生模型是?

以Bert模型舉例:性能

Logit Distillation學習

Beyond Logit Distillation:TinyBert

Curriculum Distillation:

Dynamic Early Exit:FastBert。

5.python在內存上作了哪些優化?

python經過內存池來減小內存碎片化,提升執行效率。主要經過引用計數來完成垃圾回收,經過標記-清除解決容器對象循環引用形成的問題,經過分代回收提升垃圾回收的效率。

6.怎麼節省內存?

  • 手動回收不須要用的變量;
  • 將數值型數據轉化爲32位或16位(對數據類型進行限制)

代碼示例以下:

def reduce_mem_usage(props):
    # 計算當前內存
    start_mem_usg = props.memory_usage().sum() / 1024 ** 2
    print("Memory usage of the dataframe is :", start_mem_usg, "MB")
    
    # 哪些列包含空值,空值用-999填充。why:由於np.nan當作float處理
    NAlist = []
    for col in props.columns:
        # 這裏只過濾了object格式,若是你的代碼中還包含其餘類型,請一併過濾
        if (props[col].dtypes != object):
            
            print("**************************")
            print("columns: ", col)
            print("dtype before", props[col].dtype)
            
            # 判斷是不是int類型
            isInt = False
            mmax = props[col].max()
            mmin = props[col].min()
            
            # Integer does not support NA, therefore Na needs to be filled
            if not np.isfinite(props[col]).all():
                NAlist.append(col)
                props[col].fillna(-999, inplace=True) # 用-999填充
                
            # test if column can be converted to an integer
            asint = props[col].fillna(0).astype(np.int64)
            result = np.fabs(props[col] - asint)
            result = result.sum()
            if result < 0.01: # 絕對偏差和小於0.01認爲能夠轉換的,要根據task修改
                isInt = True
            
            # make interger / unsigned Integer datatypes
            if isInt:
                if mmin >= 0: # 最小值大於0,轉換成無符號整型
                    if mmax <= 255:
                        props[col] = props[col].astype(np.uint8)
                    elif mmax <= 65535:
                        props[col] = props[col].astype(np.uint16)
                    elif mmax <= 4294967295:
                        props[col] = props[col].astype(np.uint32)
                    else:
                        props[col] = props[col].astype(np.uint64)
                else: # 轉換成有符號整型
                    if mmin > np.iinfo(np.int8).min and mmax < np.iinfo(np.int8).max:
                        props[col] = props[col].astype(np.int8)
                    elif mmin > np.iinfo(np.int16).min and mmax < np.iinfo(np.int16).max:
                        props[col] = props[col].astype(np.int16)
                    elif mmin > np.iinfo(np.int32).min and mmax < np.iinfo(np.int32).max:
                        props[col] = props[col].astype(np.int32)
                    elif mmin > np.iinfo(np.int64).min and mmax < np.iinfo(np.int64).max:
                        props[col] = props[col].astype(np.int64)  
            else: # 注意:這裏對於float都轉換成float16,須要根據你的狀況本身更改
                props[col] = props[col].astype(np.float16)
            
            print("dtype after", props[col].dtype)
            print("********************************")
    print("___MEMORY USAGE AFTER COMPLETION:___")
    mem_usg = props.memory_usage().sum() / 1024**2 
    print("Memory usage is: ",mem_usg," MB")
    print("This is ",100*mem_usg/start_mem_usg,"% of the initial size")
複製代碼

7.pandas庫怎麼讀取超大型文件?

能夠採起分塊讀取數據的方式。

代碼示例以下:

data_path = r'E:\python\Study\BiGData\demo.csv'
def read_bigfile(path):
    # 分塊,每一塊是一個chunk,以後將chunk進行拼接
    df = pd.read_csv(path, engine='python', encoding='gbk', iterator=True)  
    loop = True
    chunkSize = 10000
    chunks = []
    while loop:
        try:
            chunk = df.get_chunk(chunkSize)
            chunks.append(chunk)
        except StopIteration:
            loop = False
            print("Iteration is stopped.")
    df = pd.concat(chunks, ignore_index=True)
after_df = read_bigfile(path = data_path)
複製代碼

8.無重複字符的最長子串

該題爲leetcode-3,難度:【中等】

方法:雙指針 + sliding window

定義兩個指針 start 和 end 獲得 sliding window

start 初始爲0,用end線性遍歷每一個字符,用 recod 記錄下每一個字母最新出現的下標

兩種狀況:一種是新字符沒有在 record 中出現過,表示沒有重複,一種是新字符 char 在 record 中出現過,說明 start 須要更新,取 start 和 record[char]+1 中的最大值做爲新的 start。

須要注意的是:兩種狀況都要對record進行更新,由於是新字符沒在record出現過的時候須要添加到record中,而對於出現過的狀況,也須要把record中對應的value值更新爲新的下標。

代碼:

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        record = {}
        start,res = 0,0
        for end in range(len(s)):
            if s[end] in record:
                start = max(start, record[s[end]] + 1)
            record[s[end]] = end
            res = max(res, end - start + 1)
        return res
複製代碼

時間複雜度:O(n)

空間複雜度:O(1)

9.判斷鏈表是否有環、鏈表環的入口

判斷鏈表是否有環爲leetcode-141題

提供兩種解題方法,以下:

方法一:哈希表

遍歷全部節點,每次遍歷一個節點時,判斷該節點此前是否被訪問過。

若是被訪問過,說明該鏈表是環形鏈表,並返回True,若是沒有,則將該節點加入到哈希表中,遍歷完成便可。

代碼以下:

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        seen = set()
        while head:
            if head in seen:
                return True
            seen.add(head)
            head = head.next
        return False
複製代碼

時間複雜度:O(n)

空間複雜度:O(n)

方法二:快慢指針

定義兩個指針,一快一慢,滿指針每一移動一步,快指針每次移動兩步,因爲快指針比慢指針慢,若是鏈表有環,則快指針必定會和慢指針相遇。

代碼以下:

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        fast = slow = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if fast == slow:
                return True
        return False
複製代碼

時間複雜度:O(N)

空間複雜度:O(1)

鏈表環的入口 爲leetcode-142題

解題思路:使用快慢指針

首先,咱們要作如下設定,設鏈表共有 a + b個節點,其中鏈表頭部到鏈表入口(不計鏈表入口節點)有 a 個節點,鏈表環有 b 個節點,同時設快指針走了 f 步,慢指針走了 s 步;

顯然,因爲快指針是慢指針的兩倍,所以有:f = 2s

若是兩個指針第一次相遇,則知足:f = s + nb(n表示n個環),也就是 fast 比 slow 多走了 n 個環的長度;

由上可得:當兩個指針第一次相遇,有s = nb, f = 2nb

如今須要解決的問題,咱們如何知道 a 的大小?

假設如今兩指針第一次相遇:

對慢指針來講,若是讓慢指針走到鏈表入口節點,須要 a + nb步,而在相遇時,已經走了 nb 步了,所以,再讓慢指針走 a 步就能夠走到鏈表入口節點了;

對快指針來講,若是讓快指針從頭指針開始走 a 步,快指針也正好走到鏈表入口節點;

因而可知,兩指針發生第二次相遇的時候,恰好都在鏈表入口處。

代碼以下:

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        fast = slow = head
        while True:
            if not (fast and fast.next):return
            fast = fast.next.next
            slow = slow.next
            if fast == slow:break
        fast = head
        while fast != slow:
            fast = fast.next
            slow = slow.next
        return fast
複製代碼

時間複雜度 O(N)

空間複雜度 O(1)


AI充電季,開寶箱免費學正價課!

更有200本紙質書等,來就送! >>>AI充電季,開寶箱免費學正價課,200本紙質書等包郵送!-七月在線

發佈於剛剛

相關文章
相關標籤/搜索