热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Word2vecfromscratch(Skip-gram&CBOW)

在自然語言處理領域中,如何透過向量表達一個詞彙,是近幾年非常火熱的議題,在distributedrepresentation(densevector)尚未風行前,大多數的任務都以1-hotencoding作為詞彙的表示,其方法得到了高維度的稀疏向量,雖容易理解、簡單計算,但也帶來許多副作用;直至2013年,ThomasMikolov等人提出了word2vec,word2vec引用了一個概念,作者導
Word2vec from scratch (Skip-gram & CBOW)

Preface

在自然語言處理領域中,如何透過向量表達一個詞彙,是近幾年非常火熱的議題,在 distributed representation(dense vector) 尚未風行前,大多數的任務都以 1-hot encoding 作為詞彙的表示,其方法得到了高維度的稀疏向量, 雖容易理解、簡單計算,但也帶來許多副作用;直至 2013 年,Thomas Mikolov 等人提出了 word2vec,word2vec 引用了一個概念,作者導入了1957年 J. R. Firth 提出的想法,要充分地理解一個詞彙的語意,首先要先理解它的上下文資訊。

“You shall know a word by the company it keeps” (J. R. Firth 1957: 11)

舉例來說,給定一個足夠大的語料,「狗」的上下文可能會常出現「跑」、「吠」、「跳」、「動物」等詞,我們如果能透過這些上下文兜出「狗」的詞彙向量,則將「狗」賦予了不同於 1-hot vector 的向量表示。

因此,具有類似上下文的詞彙,將會有相近的語意向量,例如「狗」和「犬」計算餘弦相似度時,其值相較於「狗」和「蛋糕」來得大。

本文針對曾使用過 word2vec 且有基本概念,但對於內部詳細的運作還不太清楚的讀者,進行其原理和數學公式簡單淺白的梳理,希望看完本文的讀者能對 word2vec 有更深一層的認識。

Skip-gram & CBOW

word2vec 提出了兩個方法,Skip-gram 和 CBOW。

Skip-gram 是利用中心詞來預測上下文,如下圖所示,假定「柯文哲」為模型的輸入,則輸出為固定 window 長度的上下文詞彙,如「台北 」、「市長」、「參加」、「大甲」。

台北 w(t-2)/市長 w(t-1)/柯文哲 w(t)/參加w(t+1)/大甲 w(t+2)/媽祖/遶境

Word2vec from scratch (Skip-gram & CBOW)

CBOW 則是利用上下文來預測中心詞,假定「台北 」、「市長」、「參加」、「大甲」為輸入,則輸出為中心詞彙「柯文哲」。

Word2vec from scratch (Skip-gram & CBOW)

Skip-gram model

首先來談談 skip-gram ,如下式,給定中心詞 w 和模型參數 θ 要計算上下文 c 出現的機率 p(c|w; θ),其中 C(w) 表示中心詞 w 周圍的上下文詞彙。

Word2vec from scratch (Skip-gram & CBOW)
(式子2)

針對所有在語料 Text 的中心詞 w,我們希望能透過更新模型參數 θ,最大化上下文詞彙的出現機率乘積,當訓練逐漸收斂時,便可取出 θ 參數中,代表詞彙向量的部分,如下圖的 W_(VxN),假定我們有個 V 相異詞彙,每個詞彙有 N 維向量,則它可作為大小 V x N 的詞向量 lookup table ,輸入詞彙索引,便可取出該詞彙的對應向量。

Word2vec from scratch (Skip-gram & CBOW)
Skip-gram model

假定下例為唯一的待訓練語料

台北 市長 柯文哲 參加 大甲 媽祖 遶境

中心詞 w = [台北, 市長, 柯文哲, 參加, 大甲, 媽祖, 遶境]

當設定 window size 為 1時,我們可將所有中心詞的上下文都找出來:

C(台北) = [__, 市長] ,

C(市長) = [台北, 柯文哲],

C(柯文哲) = [市長, 參加],

C(參加) = [柯文哲, 大甲],

C(大甲) = [參加, 媽祖],

C(媽祖) = [大甲, 遶境],

C(遶境) = [媽祖, __]

因此我們藉由更新 θ,最大化下面的條件機率連乘積:

argmax (p(市長|台北; θ)p(台北 |市長; θ) p(柯文哲 |市長; θ)p(市長|柯文哲; θ) p(參加|柯文哲; θ) p(柯文哲|參加; θ) p(大甲|參加; θ)p(參加|大甲; θ) p(媽祖|大甲; θ) p(大甲|媽祖; θ)p(遶境|媽祖; θ) p(媽祖|遶境; θ) )

完成訓練後,便可從θ中取出詞向量 matrix。

為方便後續式子的呈現,我們將式子 1 簡化為下列式子 2 ,其中 D 表示中心詞與其對應上下文的所有 pairs (w, c)。

Word2vec from scratch (Skip-gram & CBOW)
(式子2)

接著我們要將 p(c|w; θ) 此條件機率轉化為模型中參數的實際運作,如式子3,給定某中心詞 w 和模型參數 θ,要計算詞彙 c 的機率。

式子 3 分子的部分,將中心詞向量 v_w 和上下文詞向量 v_c 進行點積 (dot product) 作為指數函數 (e) 的輸入,可以想像的是,若兩個詞向量是接近的,那計算出來的點積將會是較大的純量,反之,若兩向量相差很大,則點積結果會變小;我們知道指數函數 exp(x),當x越大,則 exp(x) 就越大,因為我們的目標是讓 p(c|w; θ) 機率值越大越好,所以也就是 v_w & v_c 點積越大越好,換句話說,我們的實際目標就是讓中心詞與其上下文向量盡可能的接近。

而 p(c|w; θ) 中的 θ 以式3的分子來說,就是 中心詞 v_w 和 上下文 v_c 所對應的詞向量。

式子 3 分母的部分,我們計算語料中,所有上下文詞彙分別與中心詞彙向量計算點積的總合,因此結合分子,就變成了一個 softmax 函數,透過此函數,可以得到每一個特定上下文詞彙基於中心詞的出現機率,雖然嚴格來說,softmax 輸出值不算是機率,也因為每一個 element 的 softmax 輸出皆介於 0-1 且其總和為 1,因此我們姑且把其輸出值視為發生可能性高低。

Word2vec from scratch (Skip-gram & CBOW)
(式子3)

仔細觀察一下式子 2 發現,小數的大量連乘積,在實務上會有溢位的風險,因此在處理這類的問題,我們傾向將乘除法想辦法轉換成加減法,高中數學有教, log(a/b) = log(a) – log(b),因此我們將式子2 取 log,即得到式子4 的結果,亦是 skip-gram 理想上 的目標函數,數學上我們稱之為 maximum log likelihood (最大對數似然估計)。

此外,word2vec 可視為一個淺層網路架構,由於速度的考量,模型中沒有使用到任何的 activation function,因此無任何非線性變換;也因其特點是不斷地採用點積來作為兩向量相似的依據,因此作者將此作法稱之為 log bi-linear model。

Word2vec from scratch (Skip-gram & CBOW)
(式子4)

這裡值得一提的是,語料中每一個詞彙都有兩種身分,可以是中心詞,也可以是別的中心詞的上下文詞彙,因此在實作上,就如下圖所示 ,word2vec 將每個詞彙都預設了兩個向量(中心詞向量矩陣 W & 上下文向量矩陣 W’)。至於為什麼這樣做,首先是參數更新上,若W & W’ 相同,則必須有機制,能支援兩向量矩陣同步更新。

另外,以 dog 為例,通常文本中,很少會在一個小的 windows 中,有兩個相同詞彙同時出現的情況發生,也就是說 dog 一詞的周圍是 dog 的可能性不高,因此模型肯定會讓 p(dog|dog) 機率越低越好,但若套入上式會發現,v(dog) 與 v(dog) 兩個相同向量的點積其純量肯定是大的,這則會跟 p(dog|dog) 機率越低越好相違背而造成矛盾的現象,因此,word2vec 就將此情境變為 u(dog) & v(dog) 的點積,便不會有上述問題發生。

Word2vec from scratch (Skip-gram & CBOW)
Skip-gram model

講到這裡,讀者心理可能會冒出一個疑問,skip-gram 圖和上述的公式具體來說是怎麼結合在一起呢?

我們參考上圖,並將之分為下列幾個步驟來說明:

假設輸入了一個中心詞彙 x_k,其周圍有 C 個上下文詞彙,則…

  1. input layer 為中心詞 x_k 的 1-hot vector,維度是 1 x V。
  2. 通過預先初始化好的權重 W,W 的大小為相異總字數 V 與詞向量維度 N ,V x N 的矩陣,此 W 訓練完畢後,將成為日後的詞向量矩陣。
  3. 完成第二步後, hidden layer 獲得中心詞維度 N 的詞向量。
  4. 從 hidden layer 到 Output layer 做了 C 次的前向傳遞,每次的傳遞都與相同的 W’ 權重矩陣相乘產生 V 維的向量 y,這邊的 W’ 表示上下文的詞向量矩陣,但不同於W的是,當詞彙的身分是上下文時,才會對應到此向量;而的 C 表示該中心詞彙的上下文數量,透過 window size 決定,因此總和的大小是 C x V。
  5. 將這 C 次所產生的值 y_1 到 y_c 通過 Softmax function 轉換,這裡要注意的是,Softmax 分母的計算是由 y 每一個維度值而來,而非僅透過 y_1 到 y_c 所對應維度,因此我們可以將 y 的每一個維度值視為所有相異詞彙與該中心詞彙的點積,點積越大,機率值就越大。
  6. 由於 y_1 到 y_C 皆為 x_k 的中心詞,因此給定中心詞 x_k 我們要最大化 y_1 到 y_C 的條件機率值,而每一個條件機率值就以 Softmax 來模擬。

因此步驟一到步驟六即跟 skip-gram 公式不謀而合,目標是最大化上下文詞彙出現的機率。

Negative Sampling 負面採樣

從錯誤中學習、從失敗中成長,模型除了學習正向的資料外,我們也要同時提供錯誤的資料給模型,並告訴它什麼是對的什麼是錯的。

假定文本中有 10 萬個相異詞彙,如果要按照上述的策略進行模型訓練,那每次計算目標函數的 likelihood ,除了提供正面教材 (中心詞、上下文) pair 給模型外,還要提供其他近 10萬條非上下文詞彙供模型學習,因此我們就要以這10萬筆作為基底作最大似然估計,肯定在訓練速度和記憶體上會是一大挑戰,對於此問題作者提出了 Negative sampling 的概念,也就是說,與其對十萬筆詞彙作運算,我們能不能僅挑選出少量的負面案例,就作為模型學習、訓練的依據。

以下為例,已知文本中詞彙「柯文哲」的上下文不存在如「吠」、「叫」、「動物」等詞彙,我們可以將此組合作為模型的負面教材,讓模型學習到基於某中心詞什麼是正確、合理的上下文,什麼不是。

上下文 : [吠、叫、動物]

中心詞 : 柯文哲。

因此,我們將式子作了一些修改,如式子 5 , D 表示所有真實出現在語料中(w中心詞、c上下文) pair,給定 w, c,模型要去計算 (c, w) pair真實出現在語料中的機率。

Word2vec from scratch (Skip-gram & CBOW)
(式子5)

其中 p(D=1|w,c;θ)可視為一種二元分類,即 w, c 是否真實存在於語料、還是是虛造的c並非w的上下文,因此 word2vec 利用 sigmoid 函數,任何數值通過 sigmoid 後,皆會介於 0-1 之間,因此可透過此函數來模擬 (c,w) 是否是真實存在的可能性,若值靠近 1,則表示c是w的上下文,反之,表示 (c,w) 為隨機生成的 pair。

Word2vec from scratch (Skip-gram & CBOW)
(式子6)
Word2vec from scratch (Skip-gram & CBOW)
sigmoid function

若沒有任何負面訓練資料,則我們的目標函數就如式子 7 所述。

Word2vec from scratch (Skip-gram & CBOW)
(式子7)

接著我們要將負面的訓練資料一併加入,如下式所示,公式中除了要最大化(w,c) ∈ D 存在於真實文本的機率外,也要最大化 (w, c) ∈ D’ 不存在真實文本的機率,當給定任意一組 (w,c),已知 p(d=0|w,c)+ p(d=1|w,c)=1,因此,為了式子的簡潔性,可以將 p(d=0|w,c) 統一轉換成 1 – p(d=1|w,c)。

接著如上面介紹,將連機率連乘積取 log 且其機率值使用 sigmoid 函數來表示,就成了式子8最後的數學式。

Word2vec from scratch (Skip-gram & CBOW)
(式子8)

為簡易表示,我們將 σ()視為 sigmoid 函數,因此最終結果如式子 9。

Word2vec from scratch (Skip-gram & CBOW)
(式子9)

而該怎麼聰明的從 D’ 中選擇負面採樣的數量,作者也作了一些實驗,從下表可以發現,Negative Sampling 數量在 15 時,所訓練出來的詞向量,在句法和語意的任務上都有較佳的表現。

Word2vec from scratch (Skip-gram & CBOW)

另一個問題,則是我們該如何進行採樣,參考詞彙分布圖,假設每一個詞彙都有一個固定的長度,且其長度總和為1,我們要基於詞彙的長度,隨機公平的採樣詞彙,作為模型的負面教材。

Word2vec from scratch (Skip-gram & CBOW)
詞彙分布圖

因此長度越大的詞彙越容易被取樣,而詞彙的長度就套用式子10,計算所有詞彙的出現次數總合為分母,欲計算長度的詞彙出現次數作為分子。

Word2vec from scratch (Skip-gram & CBOW)
(式子10)

Corpus :台北 市長 柯文哲 參加 大甲 媽祖 遶境

total length : 7/7 = 1

length of 柯文哲 :1/7

probability of 柯文哲 being sampled : 1/7 = 0.1429 = 14.29%

Subsampling of Frequent Words

因為停用詞、功能詞總散布在文本中,若採用上式的作法容易採樣到那些詞彙,那對於語意向量的訓練相對來說是沒有幫助的,因此,如式子11,作者將出現次數取根號 3/4,能有效降低停用詞、功能詞被取樣的機率,實驗顯示,Magic number 3/4 確實對於詞向量的品質有不少的幫助。

Word2vec from scratch (Skip-gram & CBOW)
(式子11)

如下圖,經過 subsampling 後,bombastic 被取樣的機率約提升了三倍,而高頻詞 is 僅有微幅增加,經 normalize 後可預期 is被採樣的機率將下降,而 Constitution 和 bombastic 被採樣的機率將大幅上升。

Word2vec from scratch (Skip-gram & CBOW)

Hierarchical Softmax (CBOW)

除了 Negative sampling 外,作者亦提出了一個方法 Hierarchical Softmax ,能快速的縮短訓練所需要的時間。

傳統作法,針對每一筆訓練資料,我們需要花費 10 萬次的計算才得以獲得 likelihood,因此作者試著將輸出層作一些改變,試想如果將 10 萬個節點的輸出,建構一顆二元樹,那時間複雜度將會從 O(n) 降為 O(logn)。

作者利用 霍夫曼编码 (huffman coding) 來建立二元樹,其精神是經由統計每個詞彙的出現頻率,來決定詞彙的編碼,也就是說,當某個詞彙有高的詞頻時,其編碼位元數會較低,因為它很常被訪問,若能降地其編碼位元數,則能有效減輕運算所需時間。

因此每一個詞彙都其代表的編碼,如下圖,假設二元樹中,向右走是0,向左走是1,則 w_2 的編碼則為110。

Word2vec from scratch (Skip-gram & CBOW)

台北 市長 柯文哲 參加 大甲 媽祖 遶境

我們以 CBOW 為例,模型輸入上下文詞彙 (windows:2),試著預測中心詞彙是什麼。因此模型將 「台北」、 「市長」 、「參加」 、「大甲」詞向量加總作為輸入,並以中心詞「柯文哲」作為模型的輸出。

假定「柯文哲」的霍夫曼編碼維是 110(w_2),如上樹狀圖, 編碼 110需要經過三個內部節點才會抵達葉節點,每一個內部節點模型能選擇擇往右(1)或往左走(0),因此每個節點都有一個可訓練的參數 θ,分別與輸入X_w 點積後作為 sigmoid 函數的輸入,根據 sigmoid 的特性其輸出介於0-1之間,所以,可依據 sigmoid 的輸出值靠近1或靠近0,來決定要往右或往左走 (式子11)。

Word2vec from scratch (Skip-gram & CBOW)
(式子11)

因此假定 sigmoid 輸出值為內部節點向右走的機率,則式子12 為內部節點向左走的機率。

Word2vec from scratch (Skip-gram & CBOW)
(式子12)

因為模型在前處理階段,就已完成所有相異詞彙的霍夫曼編碼,因此我們可以很清楚的知道該最大化什麼東西;以「柯文哲 110」為例,在根節點時模型要最大化向左走的機率、第二個內部節點模型要最大化向左走的機率,第三個內部節點模型要最大化向右走的機率。

藉由更新 θ,最大化上述的三個機率條件機率連乘積(式子13),如此一來,才能讓模型沿著 001 的編碼,順利找到代表「柯文哲 」一詞的葉節點。

Word2vec from scratch (Skip-gram & CBOW)
(式子13)

條件機率值可有兩種情況如式子14,依照詞彙的編碼而定,若其編碼d為0 則條件機率值 p(d|x,θ)採用σ(xθ),反之若編碼d為1,p(d|x,θ)採用 1 – σ(xθ)。

Word2vec from scratch (Skip-gram & CBOW)
(式子14)

因此,條件機率值便可以式子15來表示,當 d 為 0 時,式子後項 [1- σ(xθ)]^d = 1 可忽略不見,當 d 為1時,式子前項 [σ(xθ)]^(1-d)] = 1 也可忽略不見。

Word2vec from scratch (Skip-gram & CBOW)
(式子15)

最後我們可以將 CBOW Hierarchical Softmax 整理成如式子16,每一筆的訓練資料都將基於中心詞的編碼,走訪霍夫曼樹,假定中心詞編碼為l^w,除了 j=1 為根節點外(沒有方向性),j=2開始一直到葉節點第l^w步,每一個節點都有其對應的方向,表示需要走左邊或走右邊才可以抵達該節點。

為了簡化計算和避免溢位的風險,我們將對數似然函數的機率乘積取log,從乘積值轉為取其總合。

Word2vec from scratch (Skip-gram & CBOW)
(式子16)

實務上,模型將預設定的 batch size 的訓練資料,一次性地產生 likelihood value,每一批次所計算出的 likelihood value ,將利用 back propagation 作為參數 θ 更新的依據,我們可將式子16簡化為式子17,此式即為 CBOW Hierarchical Softmax 最終的 log likelihood function。

Word2vec from scratch (Skip-gram & CBOW)
(式子17)

Conclusion

本文簡述了 word2vec 使用到的兩個核心技術,CBOW 和 Skip-gram,且詳述了 word2vec 訓練優化的兩個技巧,Negative Sampling & Hierarchical Softmax,並直白的梳理其公式的原理。

word2vec 是 NLP 近年內之所以能快速成長的最主要原因,當今作為一名自然語言處理研究者,各式各樣的 NLP 任務為達到 state-of-the-art 成果,皆套用了如 Google BERT 、OpenAI GPT2 等作法,或許 word2vec 已逐漸式微,但我們必須知道,這些高大上的模型背後,仍是基於 word2vec 的概念作延伸,且這些龐大的模型在產生所謂高品質的詞向量前,最初始的詞彙表達,仍是採用如 word2vec & GloVe 方法作為詞彙的初始化,因此其重要性不言而喻。

在 NLP 持續發展的路上,我們必須鑑往知來,充分理解、感受過去偉大的研究發明,才得以站在巨人的肩膀上繼續提出新的貢獻。

References

1. Distributed Representations of Words and Phrases and their Compositionality

2. word2vec Explained: Deriving Mikolov et al.’s Negative-Sampling Word-Embedding Method


以上所述就是小编给大家介绍的《Word2vec from scratch (Skip-gram & CBOW)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 我们 的支持!


推荐阅读
  • vue使用
    关键词: ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 如何在HTML中获取鼠标的当前位置
    本文介绍了在HTML中获取鼠标当前位置的三种方法,分别是相对于屏幕的位置、相对于窗口的位置以及考虑了页面滚动因素的位置。通过这些方法可以准确获取鼠标的坐标信息。 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
author-avatar
cb
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有