關聯規則挖掘2:FP-growth算法(Frequent Pattern Growth,頻繁模式增長)

目錄

一、核心思想:一個形象的比喻

二、核心思想的具體拆解

步驟一:構建FP-tree(頻繁模式樹)

步驟二:從FP-tree中挖掘頻繁項集

為什么這很高效?

三、總結

核心思想與優勢

適用場景與缺點

四、例題

給定數據

第一步:第一次掃描數據庫,找出頻繁1項集及其支持度

第二步:第二次掃描數據庫,構建FP-tree

第三步:挖掘FP-tree,尋找頻繁項集

1. 以后綴?A?開始挖掘

步驟 1: 尋找條件模式基 (Conditional Pattern Base)

步驟 2: 構建條件FP-tree (Conditional FP-tree) for?A

步驟 3: 挖掘條件FP-tree并生成頻繁項集

2. 以后綴?E?開始挖掘

步驟 1: 尋找條件模式基 for?E

步驟 2: 構建條件FP-tree for?E

步驟 3: 挖掘條件FP-tree for?E

3. 以后綴?C?開始挖掘

步驟 1: 尋找條件模式基 for?C

步驟 2: 構建條件FP-tree for?C

步驟 3: 挖掘條件FP-tree for?C

4. 以后綴?B?開始挖掘

步驟 1: 尋找條件模式基 for?B

步驟 2: 構建條件FP-tree for?B

步驟 3: 挖掘條件FP-tree for?B

第四步:匯總所有頻繁項集

最終答案


?參考:

Python數據挖掘實戰:微課版 - 9.3 FP-growth算法 - 王磊 邱江濤 - 微信讀書

19.FpGrowth算法介紹_嗶哩嗶哩_bilibili
9.2 利用FP-tree挖掘頻繁項集的過程

FP-growth(Frequent Pattern Growth,頻繁模式增長)算法是用于高效挖掘數據集中頻繁項集的一種方法。它極大地改進了傳統的Apriori算法,核心目標仍然是找出所有滿足最小支持度閾值的項集。

其核心思想可以概括為:“分而治之”?和?“用空間換時間”


一、核心思想:一個形象的比喻

想象一下,你要統計一圖書館里所有書籍的組合借閱情況(比如,同時被借閱的書籍組合)。

  • Apriori算法(傳統方法):像一個笨拙的圖書管理員。他需要反復穿梭于各個書架之間,每次只關心“2本書的組合”,統計完后再找“3本書的組合”,如此反復。這個過程會產生大量的“候選組合”,并且需要反復掃描整個借閱記錄(數據庫),非常耗時。

  • FP-growth算法(新方法):像一個聰明的圖書管理員。他首先花一點時間,為整個圖書館建立了一個非常精巧的索引目錄(FP-tree)這個目錄不僅記錄了每本書被借閱的次數,還清晰地記錄了哪些書經常被一起借閱。當你想查詢任何書籍組合時,他無需再跑回書架只需在這個濃縮的目錄里進行查找和拼接,就能快速得到結果。

這個“精巧的目錄”就是FP-growth算法的精髓。


二、核心思想的具體拆解

FP-growth算法主要分為兩個核心步驟,完美體現了其思想:

步驟一:構建FP-tree(頻繁模式樹)

這是“用空間換時間”和“數據壓縮”的體現。

  1. 第一次掃描數據庫:統計所有單項(1項集)的支持度,并丟棄那些不頻繁的項(低于最小支持度)。

  2. 排序:將剩余的頻繁項按照支持度從高到低排序。這樣做的好處是,出現頻率高的項更靠近樹的根部,使得樹的深度盡可能小,更加緊湊。

  3. 第二次掃描數據庫:開始構建FP-tree。

    • 將每條事務(例如一次購物籃記錄?{牛奶,面包,啤酒})中的項按第二步的順序排序和過濾(例如排序后為?{啤酒,面包,牛奶})。

    • 從樹的根節點開始,為這條事務創建一條分支。如果分支的前綴與已有路徑共享,則共享節點的計數加1;如果不共享,則創建新的節點。

    • 同時,為了快速訪問樹中的節點,還維護了一個頭指針表,它鏈接了所有相同名稱的節點。

為什么這很巧妙?

  • 壓縮數據庫原始的數據庫被壓縮成了一棵FP-tree。事務數據中共享的頻繁項被合并到了同一條路徑上,大大減少了存儲空間。

  • 信息完整:這棵樹完整地保留了項集之間的關聯和頻率信息。


步驟二:從FP-tree中挖掘頻繁項集

這是“分而治之”思想的體現。

挖掘過程是遞歸的。我們不是從整個大樹開始挖,而是從小樹枝開始。

  1. 從后綴開始:從頭指針表中支持度最低的項(即樹的枝葉末梢)開始,作為當前的后綴模式(例如?{牛奶})。

  2. 尋找條件模式基:沿著頭指針表,找到FP-tree中所有包含此后綴的路徑。這些路徑去掉后綴后剩下的前綴部分,以及路徑上的計數,就構成了條件模式基。這相當于為“牛奶”這個項創建了一個子數據庫。

  3. 構建條件FP-tree:以這個條件模式基作為新的“數據庫”,重復步驟一的過程,構建一個只與“牛奶”相關的條件FP-tree

  4. 遞歸挖掘:如果條件FP-tree不是空的(例如一條單路徑),則遞歸地挖掘這棵小樹。如果它是一條單路徑,則直接生成該路徑上所有節點的組合,并與后綴模式合并,即可得到所有頻繁項集(例如,從路徑?啤酒:3,面包:3?可以得到?{啤酒,面包,牛奶}{啤酒,牛奶}{面包,牛奶})。

  5. 移動指針:處理完一個后綴后,就回頭指針表中移動到下一個支持度稍高的項(例如?{面包}),重復步驟2-4,直到處理完所有項。


為什么這很高效?

  • 分治:將挖掘整個大數據集的任務,分解為挖掘多個更小的條件數據庫的任務,問題規模指數級減小。

  • 避免候選集生成:它不需要產生大量的候選集(這是Apriori的主要瓶頸),而是通過遞歸和直接拼接來生成頻繁項集

  • 無重復掃描數據庫:整個過程中,原始數據庫只被掃描了兩次(構建FP-tree時)。之后的所有操作都是在內存中對這棵壓縮樹進行操作,速度極快。


三、總結

核心思想與優勢

方面核心思想闡述帶來的優勢
數據表示用空間換時間:花費內存構建一個高度壓縮、信息完整的數據結構(FP-tree)。大幅減少I/O開銷:僅需掃描數據庫兩次,后續操作均在內存中進行。
挖掘策略分而治之:通過遞歸地構建條件模式基和條件FP-tree,將大問題分解為多個小問題。效率極高:避免了產生海量候選集,算法復雜度通常遠低于Apriori。
搜索方法模式增長:從后綴模式出發,通過拼接前綴路徑來直接生成頻繁模式,而非通過候選和測試。精準高效:沒有無效的候選集生成和測試過程。

適用場景與缺點

  • 適用場景:非常適合挖掘稠密數據集(即事務中項之間相關性較強,共享前綴多),能獲得很好的壓縮效果和性能提升。

  • 缺點

    • 空間消耗:FP-tree及其遞歸過程中構建的條件FP-tree可能會消耗大量內存,尤其是在處理稀疏數據集或支持度閾值很低時。

    • 實現復雜度:相對于Apriori,其實現更為復雜。

FP-growth算法的核心在于創新地使用樹結構來壓縮存儲數據,并基于此結構采用分而治之的策略進行高效挖掘,從而解決了Apriori算法多次掃描數據庫和產生大量候選集的兩個主要性能瓶頸。


四、例題

給定數據

TIDItems
10A, C, D
20B, C, E
30A, B, C, E
40B, E

設定最小支持度 (min_sup):?為了演示方便,我們設定最小支持度為?2?(即出現次數 >= 2)。


第一步:第一次掃描數據庫,找出頻繁1項集及其支持度

我們統計每個商品在所有訂單中出現的總次數。

  • A: 出現在T10, T30 → 計數 = 2

  • B: 出現在T20, T30, T40 → 計數 = 3

  • C: 出現在T10, T20, T30 → 計數 = 3

  • D: 出現在T10 → 計數 = 1?(小于min_sup=2,丟棄)

  • E: 出現在T20, T30, T40 → 計數 = 3

篩選并排序后的頻繁1項集(按支持度降序排列):

商品支持度
B3
C3
E3
A2

順序為: B, C, E, A?(支持度相同時,順序可任意,但必須固定)


第二步:第二次掃描數據庫,構建FP-tree

我們為每條事務(訂單)中的商品按照上一步確定的順序(B, C, E, A)進行排序,并過濾掉非頻繁項(此例中為D)。

  1. T10:?A, C, D?→ 過濾D →?A, C?→ 按順序排序 →?C, A?(因為C的支持度3 > A的支持度2)

  2. T20:?B, C, E?→ 按順序排序 →?B, C, E

  3. T30:?A, B, C, E?→ 按順序排序 →?B, C, E, A

  4. T40:?B, E?→ 按順序排序 →?B, E


現在,我們開始構建FP-tree。Root是根節點,為空。

插入 T10:?C, A

  • 從Root開始,創建子節點?C:1

  • 從?C:1?開始,創建子節點?A:1

插入 T20:?B, C, E

  • 從Root開始,沒有?B?子節點,創建?B:1

  • 從?B:1?開始,創建子節點?C:1

  • 從?C:1?開始,創建子節點?E:1

插入 T30:?B, C, E, A

  • 從Root開始,已有?B?子節點,將其計數加1 →?B:2

  • 從?B:2?開始,已有?C?子節點,將其計數加1 →?C:2

  • 從?C:2?開始,已有?E?子節點,將其計數加1 →?E:2

  • 從?E:2?開始,沒有?A?子節點,創建新的子節點?A:1

插入 T40:?B, E

  • 從Root開始,已有?B?子節點,將其計數加1 →?B:3

  • 從?B:3?開始,沒有?E?子節點B的子節點目前是?C:2,不是?E),因此創建一個新的子節點?E:1


最終構建的FP-tree如下圖所示:
(為了清晰,我們同時維護一個頭指針表,將相同名稱的節點鏈接起來)

        Root/    \B:3    C:1/   \      \E:1   C:2    A:1\E:2\A:1

頭指針表 (Header Table):

  • B?→ 鏈接到?(B:3)

  • C?→ 鏈接到?(C:1)?->?(C:2)

  • E?→ 鏈接到?(E:1)?->?(E:2)

  • A?→ 鏈接到?(A:1)?->?(A:1)


第三步:挖掘FP-tree,尋找頻繁項集

我們從頭指針表底部的支持度最低的項開始(即A),然后向上是E,C,最后是B。

1. 以后綴?A?開始挖掘
  • 步驟 1: 尋找條件模式基 (Conditional Pattern Base)
    • 在FP-tree中,找到所有以?A?結尾的路徑。

    • 路徑1:?C:1?->?A:1?(來自T10?C, A)

      • 前綴路徑:?C:1

    • 路徑2:?B:3?->?C:2?->?E:2?->?A:1?(來自T30?B, C, E, A)

      • 前綴路徑:?B:3, C:2, E:2

    • A?的條件模式基是?{C:1}?和?{B:3, C:2, E:2}

  • 步驟 2: 構建條件FP-tree (Conditional FP-tree) for?A
    • 以條件模式基作為新的事務數據庫。

    • 事務1:?C?(計數為1)

    • 事務2:?B, C, E?(計數為路徑上的最小值,即?A?的計數1?這里需要修正:計數應取路徑末尾目標節點A的計數,即每條前綴路徑的計數應等于該路徑上A節點的計數)

      • 修正:路徑?C:1 -> A:1,A的計數是1,所以前綴路徑?C?的計數是1。

      • 路徑?B:3, C:2, E:2 -> A:1,A的計數是1,所以前綴路徑?B, C, E?的計數是1。

    • 現在統計這個新“數據庫”中項的支持度:

      • C: 1 (來自事務1) + 1 (來自事務2) = 2

      • B: 1 (來自事務2) = 1?(< min_sup=2,丟棄)

      • E: 1 (來自事務2) = 1?(< min_sup=2,丟棄)

    • 頻繁項只有?C:2

    • 條件FP-tree for?A?是一條單路徑?C:2

  • 步驟 3: 挖掘條件FP-tree并生成頻繁項集
    • 條件FP-tree是單路徑?C:2

    • 該路徑上所有項的非空組合與后綴?A?合并,即可得到頻繁項集:

      • {C}?+?{A}?=?{C, A}?(支持度 = min(2, ...) ,通常取條件模式基中計數的匯總,這里?{C,A}?的支持度是?C:1路徑的1 +?B,C,E:1路徑的1??更準確的做法:項集的支持度是其條件FP-tree根節點的計數? 這里我們最終看原始計數)

      • 從原始數據看,{C, A}?出現在T10和T30,支持度確實是2。

    • 所以,以后綴?A?挖掘出的頻繁項集是:?{C, A}?(支持度2)。

結論:包含A的頻繁項集為?{A}?(2),?{C,A}?(2)。?({A}?本身是頻繁1項集)

?

(應該是:由于項目{B},{E}不滿足最小支持度計數閾值,所以被刪除。)


2. 以后綴?E?開始挖掘

  • 步驟 1: 尋找條件模式基 for?E
    • 在FP-tree中,找到所有以?E?結尾的路徑。

    • 路徑1:?B:3?->?C:2?->?E:2?(來自T20和T30?B,C,E)

      • 前綴路徑:?B:3, C:2?(計數為?E?的計數2)

    • 路徑2:?B:3?->?E:1?(來自T40?B,E)

      • 前綴路徑:?B:3?(計數為?E?的計數1)

    • E?的條件模式基是?{B:3, C:2}?(計數2) 和?{B:3}?(計數1)。

  • 步驟 2: 構建條件FP-tree for?E
    • 事務1:?B, C?(計數2)

    • 事務2:?B?(計數1)

    • 統計新數據庫支持度:

      • B: 2 + 1 = 3 (>=2,保留)

      • C: 2 (>=2,保留)

    • 按支持度降序排序:B,?C

    • 構建條件FP-tree:

      • 插入?B, C?(計數2): Root ->?B:2?->?C:2

      • 插入?B?(計數1): Root ->?B:2?(計數+1=3)

    • 最終的條件FP-tree for?E:

      Root|B:3|C:2
  • 步驟 3: 挖掘條件FP-tree for?E————(看不懂?)末尾有解釋
    • 條件FP-tree不是空樹也不是單路徑,需要遞歸挖掘。

    • 首先,以后綴?{C, E}?開始挖掘?(從條件FP-tree的底部項C開始)

      • 尋找?{C, E}?的條件模式基: 在?E?的條件FP-tree中,找到所有以?C?結尾的路徑。路徑:B:3 -> C:2

        • 前綴路徑:?B:3?(計數為?C?的計數2)

      • 構建?{C, E}?的條件FP-tree:

        • 事務:?B?(計數2)

        • 統計支持度:B:2 (>=2,保留)

        • 條件FP-tree for?{C,E}?是單路徑?B:2

      • 挖掘?{C,E}?的條件FP-tree:

        • 生成組合:?{B}?+?{C,E}?=?{B, C, E}?(支持度2? 原始數據中出現在T20和T30,支持度2)

      • 所以,包含?{C,E}?的頻繁項集:?{C,E},?{B,C,E}

        • {C,E}?的支持度:從其條件模式基?B:3(計數2) 可以看出計數為2。原始數據中出現在T20和T30,支持度2。

    • 然后,處理后綴?{E}?本身:條件FP-tree中有?B:3,所以?{B, E}?是頻繁的。

    • 最終,包含?E?的頻繁項集:

      • {E}?(3)

      • {B, E}?(3) (來自條件FP-tree中的?B:3)

      • {C, E}?(2) (來自上面的挖掘)

      • {B, C, E}?(2) (來自上面的挖掘)


3. 以后綴?C?開始挖掘
  • 步驟 1: 尋找條件模式基 for?C
    • 在FP-tree中,找到所有以?C?結尾的路徑。

    • 路徑1:?B:3?->?C:2?(來自T20和T30?B,C,...)

      • 前綴路徑:?B:3?(計數為?C?的計數2)

    • 路徑2:?Root?->?C:1?(來自T10?C,...)

      • 前綴路徑:?{}?(空,計數為?C?的計數1)

    • C?的條件模式基是?{B:3}?(計數2) 和?{}?(計數1)。

  • 步驟 2: 構建條件FP-tree for?C
    • 事務1:?B?(計數2)

    • 事務2:?{}?(空集,計數1) //空集無法形成項集,忽略

    • 統計支持度:B:2 (>=2,保留)

    • 條件FP-tree for?C?是單路徑?B:2

  • 步驟 3: 挖掘條件FP-tree for?C
    • 條件FP-tree是單路徑?B:2

    • 生成組合:?{B}?+?{C}?=?{B, C}?(支持度2)

    • 所以,包含?C?的頻繁項集:

      • {C}?(3)

      • {B, C}?(2)


4. 以后綴?B?開始挖掘
  • 步驟 1: 尋找條件模式基 for?B
    • 在FP-tree中,找到所有以?B?結尾的路徑。B?是直接掛在Root下的。

    • 路徑:?Root?->?B:3

      • 前綴路徑:?{}?(空,計數為?B?的計數3)

    • B?的條件模式基是空。

  • 步驟 2: 構建條件FP-tree for?B
    • 條件模式基是空,因此條件FP-tree為空。

  • 步驟 3: 挖掘條件FP-tree for?B
    • 無法生成新的頻繁項集。

    • 包含?B?的頻繁項集只有它自己:?{B}?(3)。


第四步:匯總所有頻繁項集

將所有步驟中找到的頻繁項集匯總,并去重({A},?{B},?{C},?{E}?在第一步已得到)。

頻繁1項集 (Frequent 1-itemsets):

  • {A}: 2

  • {B}: 3

  • {C}: 3

  • {E}: 3

頻繁2項集 (Frequent 2-itemsets):

  • {C, A}: 2

  • {B, E}: 3

  • {C, E}: 2

  • {B, C}: 2

頻繁3項集 (Frequent 3-itemsets):

  • {B, C, E}: 2

頻繁4項集 (Frequent 4-itemsets):

至此,我們使用FP-growth算法完整地找出了給定數據集中的所有頻繁項集。整個過程的核心在于構建FP-tree并通過遞歸挖掘條件模式基來避免生成大量的候選集。

最終答案

Python數據挖掘實戰:微課版 - 9.3 FP-growth算法 - 王磊 邱江濤 - 微信讀書

細節補充

我們現在的任務是從?E的條件FP-tree?里挖寶貝。這棵樹長這樣:

(Root)|
(B:3)|
(C:2)

目標:找到所有帶?E?的寶貝組合(比如?{B,E},?{C,E},?{B,C,E})。


第一步:看樹,直接拿到第一個寶貝

  • 樹上寫著?B:3

  • 意思是:B?和?E?一起出現了 3 次。

  • ??所以,我們找到了第一個寶貝:{B, E}


第二步:處理樹上的下一個點?C

樹上還有一個?C:2掛在?B?下面。我們不能直接用它,需要“放大鏡”看仔細。

為什么要為?{C,E}?再建一棵樹?
答:為了搞清楚?C?是和誰一起出現的,這樣才能拼出更大的寶貝。

怎么做?3個小步:

  1. 找?C?的路徑:在?E?的樹里,找到通到?C?的路。只有一條:B -> C

  2. 看這條路的意思:這條路?B -> C?計數是2。

    • 翻譯BCE?這三個家伙一起出現了 2 次

  3. 建新樹:我們就為?C?和?E?這個組合,建一棵超小的新樹,只記錄和它倆一起玩的人。

    • 這棵新樹只有:(B:2)

    • 意思:和?C、E?一起玩的,只有?B,而且玩了2次。


第三步:挖這棵超小的新樹

新樹?(B:2)?非常簡單,一眼就能看穿。

  • 它告訴我們兩件事:

    1. ??{C, E}?這個組合自己出現了 2 次。(因為?B?出現2次的前提是?C?和?E?肯定也在)

    2. ??{B, C, E}?這個更大的組合出現了 2 次。(就是?B?自己加上?C?和?E


最終我們找到了所有帶?E?的寶貝:

從?E?的樹本身:{B, E}?(3次)

從為?{C,E}?建的小樹里:{C, E}?(2次),{B, C, E}?(2次)

(再加上最開始就知道的?{E}?自己)


FP-growth算法經典面試題

1. 請簡要說明FP-growth算法的核心思想是什么?

高分回答:
“FP-growth算法的核心思想是‘分而治之’和‘用空間換時間’。它通過兩次掃描數據庫,構建一個高度壓縮的數據結構——FP樹(Frequent Pattern Tree),將原始數據完整的頻次信息壓縮存儲在其中。后續的挖掘過程不再需要反復訪問原始數據庫,而是通過遞歸地在FP樹上構建條件模式基和條件FP樹來挖掘全部的頻繁項集。這種方法完美避免了Apriori算法中耗時的候選集生成與測試過程。”

關鍵詞:?分而治之、空間換時間、FP樹、兩次掃描、條件模式基、遞歸挖掘、避免候選集生成。


2. 和Apriori算法相比,FP-growth有什么優缺點?

高分回答:
“優點是效率非常高。主要體現在兩方面:第一,它通常只需要掃描兩次數據庫,而Apriori需要掃描K+1次(K為最長頻繁項集長度),I/O開銷大大減少。第二,它不產生候選集,徹底避免了Apriori中候選集數量爆炸的問題。

缺點主要是空間消耗可能較大FP-tree及其遞歸構建的條件FP-tree需要存儲在內存中,數據集非常稀疏或最小支持度設置得很低時,樹的規模可能會很大,對內存是一個考驗。”

背誦模板:

  • 優點:快。?掃描次數少(2次 vs. K+1次),無候選集。

  • 缺點:可能占內存。?樹結構在密集數據下壓縮性好,但稀疏數據下可能內存消耗大。


3. 解釋一下什么是“條件模式基”(Conditional Pattern Base)?

高分回答:
“條件模式基是FP-growth算法遞歸挖掘過程中的一個核心概念。當我們要挖掘以某個項(比如項X)為后綴的所有頻繁項集時,我們需要在FP樹中找到所有包含X的路徑。這些路徑中,去掉后綴項X之后的前綴部分,以及路徑的計數信息,就共同構成了項X的條件模式基。它本質上是一個子數據庫,記錄了所有與X頻繁共現的項及其頻次,是構建更小子樹(條件FP-tree)的基礎。”

關鍵詞:?包含X的路徑、去掉X后的前綴、子數據庫、構建條件FP-tree的基礎。


4. FP-growth算法在什么情況下效率會下降?

高分回答:
“主要在兩種情況下效率會相對下降:

  1. 數據集非常稀疏時:這意味著事務中物品的共同前綴很少,導致構建出的FP-tree分支很多,壓縮效果不佳,樹會變得又寬又淺,占用大量內存,遞歸挖掘的效率也會降低。

  2. 最小支持度閾值設置得非常低時:這會導致大量非頻繁的項變成頻繁項,使得FP-tree的規模變得非常大,同樣會消耗大量內存和計算資源。”

關鍵詞:?數據稀疏、支持度閾值低、樹結構龐大、內存消耗大。


5. (可選) 能畫一下FP-tree的基本結構嗎?

如果問到,你可以畫一個簡單的示意圖并解釋:

        Root/  \B:3   C:1/   \     \C:2   E:1    A:1\E:2\A:1

解釋:?“從上到下表示項的先后順序,節點上的數字是計數。從根節點到任意一個節點就形成一條路徑,代表一個項集的出現模式。比如?B:3 -> C:2 -> E:2?這條路徑,表示項集?{B, C, E}?出現了2次。”


面試實戰技巧
  1. 先總后分:先一句話總結核心思想,再應要求展開細節。

  2. 對比突出:談到FP-growth,必提Apriori,用對比凸顯你的理解深度。

  3. 揚長避短:問優缺點時,先說優點,再“誠實”地提到缺點,并說明在什么情況下缺點會成為問題。

  4. 自信背誦:把這些答案背熟,面試時就能脫口而出,顯得非常熟練。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/93965.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/93965.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/93965.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在IDEA中DEBUG調試時查看MyBatis-Plus動態生成的SQL語句

在IDEA中DEBUG調試時查看MyBatis-Plus動態生成的SQL語句前言&#xff1a;動態SQL調試的痛與解決方案一、準備工作&#xff1a;調試前的檢查清單二、基礎方法&#xff1a;SqlSessionTemplate斷點調試步驟1&#xff1a;定位SqlSessionTemplate類步驟2&#xff1a;在invoke方法上設…

Linux 文本處理三劍客:awk、grep、sed 完全指南

Linux 文本處理三劍客&#xff1a;awk、grep、sed 完全指南 1. 概述 Linux 系統提供了三個強大的文本處理工具&#xff1a;awk、grep 和 sed&#xff0c;它們各有所長&#xff0c;結合使用可以高效地處理文本數據。 awk&#xff1a;擅長文本分析和格式化輸出&#xff0c;是一…

pyecharts可視化圖表組合組件_Grid:打造專業數據儀表盤

pyecharts可視化圖表組合組件_Grid&#xff1a;打造專業數據儀表盤 目錄pyecharts可視化圖表組合組件_Grid&#xff1a;打造專業數據儀表盤引言圖表1&#xff1a;Grid-Overlap-多X/Y軸示例代碼解析1. 圖表創建2. 多軸配置3. 圖表重疊4. Grid布局效果與應用圖表2&#xff1a;Gri…

【電氣工程學習】

三極管中&#xff1a;集電極C,基極B&#xff0c;發射極E接線&#xff1a;棕正藍負黑信號NPN開關輸出的是我們的0V,也叫低電平PNP開關輸出的是24V,也就是高電平&#xff08;NPN開關導通時&#xff0c;相當于把輸出端“拉”到0V&#xff08;低電平&#xff09;&#xff0c;稱為“…

【嵌入式】CAN通信

CAN 總線最初由博世于1980年代為汽車行業開發&#xff0c;能夠簡化復雜的布線網絡&#xff0c;還確保可靠和安全的數據傳輸。 1.CAN技術解釋 CAN網絡中的每個節點&#xff0c;都是平等的&#xff0c;沒有主次之分&#xff0c;這一點和SPI和I2C不同。每個節點都可以在需要的時…

Apache ShenYu網關與Nacos的關聯及如何配合使用

Apache ShenYu 網關與 Nacos 之間的關系可以概括為 “協作互補”:Nacos 作為 服務注冊與配置中心,為 ShenYu 提供動態的服務發現和配置管理能力,而 ShenYu 作為 流量網關,依賴 Nacos 實現路由信息的動態更新和實時生效。以下是詳細解析: 1. 核心關系圖解 拉取服務列表/路…

【CPP】一個CPP的Library(libXXXcore)和測試程序XXX_main的Demo

一個CPP的Library和測試程序Demo 1. 思路描述 目錄結構 總控CMakeList.txt文件 2. Library代碼實現 2.1 XXXLib.hpp文件(對外的接口定義文件)和XXXLib.cpp文件 2.1.1 XXXLib.hpp文件 2.1.2 XXXLib.cpp文件 2.2 CXXXLibApi.hpp文件和CXXXLibApi.cpp文件(內部的API基類) 2.2.1 CX…

【YashanDB認證】學習YashanDB的探索之路:從入門到實踐

在國產數據庫蓬勃發展的浪潮中&#xff0c;選擇了YashanDB作為技術學習的切入點。這不僅讓我深入了解了數據庫的核心技術&#xff0c;也讓我深刻體會到國產數據庫在性能、可靠性和生態適配上的創新價值。以下是我在學習YashanDB過程中的經驗與感悟。 一、YashanDB基礎介紹 Ya…

element UI 和 element plus 在組件上有哪些不同

Element UI 和 Element Plus 都是基于 Vue 的桌面端 UI 組件庫&#xff0c;由同一團隊&#xff08;餓了么前端團隊&#xff09;開發和維護。Element Plus 是 Element UI 的升級版&#xff0c;專為 Vue 3 設計&#xff0c;而 Element UI 僅支持 Vue 2。以下是它們在組件層面的主…

【3D重建技術】如何基于遙感圖像和DEM等數據進行城市級高精度三維重建?

城市級高精度三維重建是融合多源空間數據&#xff08;遙感圖像、DEM、GIS矢量等&#xff09;、計算機視覺與地理信息處理技術的復雜過程&#xff0c;核心目標是構建包含“地形地物&#xff08;建筑、道路、植被等&#xff09;”的真實、高精度三維場景。其流程可分為數據準備、…

【unitrix數間混合計算】3.4 無符號小數部分標記trait(bin_unsigned.rs)

一、源碼 這段代碼定義了一個類型級二進制小數系統&#xff0c;用于在編譯時表示和驗證二進制小數部分的有效性。 use crate::number::{F0, BFrac, Bit};/// 標記合法的二進制小數部分類型 pub trait BinFrac: Copy Default static {}// 空小數部分&#xff08;表示值為0&…

從一次 DDoS 的“死亡回放”看現代攻擊鏈的進化

本文記錄的是作者上周在測試環境真實踩到的坑。為了讓讀者能復現并親手體驗防御思路&#xff0c;文末給出了一份最小可運行的 Go 腳本&#xff0c;支持本地壓測 日志回放&#xff0c;方便對比加防護前后的差異。攻擊現場還原 周一凌晨 2:14&#xff0c;監控群里突然彈出告警&a…

LeetCode熱題100--101. 對稱二叉樹--簡單

1. 題目 給你一個二叉樹的根節點 root &#xff0c; 檢查它是否軸對稱。 示例 1&#xff1a;輸入&#xff1a;root [1,2,2,3,4,4,3] 輸出&#xff1a;true 示例 2&#xff1a;輸入&#xff1a;root [1,2,2,null,3,null,3] 輸出&#xff1a;false 2. 題解 /*** Definition for…

Pub/Sub是什么意思

Pub/Sub&#xff08;發布/訂閱模式&#xff09;?? 是一種異步消息通信范式&#xff0c;用于分布式系統中不同組件之間的解耦通信。它的核心思想是將消息的發送方&#xff08;發布者&#xff09;?? 和接收方&#xff08;訂閱者&#xff09;?? 分離&#xff0c;通過一個中間…

Redisson3.14.1及之后連接阿里云redis代理模式,使用分布式鎖:ERR unknown command ‘WAIT‘

文章目錄一、問題背景1、問題原因2、阿里云對Redisson的支持二、解決方案1、繼續使用Redisson3.14.0版本2、阿里云redis改為直連模式3、升級Redisson版本到 3.47.0一、問題背景 1、問題原因 阿里云Redis分直連和代理模式&#xff0c;其中代理模式是不支持WAIT命令的。 目前嘗…

Linux: RAID(磁盤冗余陣列)配置全指南

Linux&#xff1a;RAID&#xff08;磁盤冗余陣列&#xff09;配置一、RAID 核心概念 RAID&#xff08;Redundant Array of Independent Disks&#xff0c;磁盤冗余陣列&#xff09;通過將多個物理磁盤組合為一個邏輯存儲設備&#xff0c;實現提升讀寫性能、增強數據安全性或平衡…

《GPT-OSS 模型全解析:OpenAI 回歸開源的 Mixture-of-Experts 之路》

目錄 一、引言 二、GPT-OSS 模型簡介 1. 版本與定位 2. 架構設計與技術亮點 2.1 Mixture-of-Experts&#xff08;MoE&#xff09;架構 2.2 高效推理機制與優化技術 2.3 模型對比 三、模型部署 1. 安裝相關依賴 1.1 uv 安裝 1.2 conda 安裝 1.3 Transformers 運行 g…

【力扣熱題100】雙指針—— 接雨水

題目 給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖&#xff0c;計算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 注意&#xff1a;答案中不可以包含重復的三元組。輸入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 輸出&#xff1a;6 解釋&#xff1a;上面是由…

51單片機拼接板(開發板積木)

一、前言 1.1 背景 讀書那會兒&#xff08;2013年左右&#xff09;網上接了很多51單片機的設計。 當時有個痛點: 每張板子都是定制的&#xff0c;畫板子&#xff0c;打樣&#xff0c;寫代碼需要花費很多時間。 希望有一張板子&#xff0c;能夠實現絕大多數單片機的功能&#xf…

使用segment-anything將目標檢測label轉換為語義分割label

使用segment-anything將目標檢測label轉換為語義分割label一、segment-anything簡介二、segment-anything安裝2.1安裝方法2.2預訓練模型下載三、將目標檢測label轉換為語義分割label3.1示例代碼3.2代碼說明一、segment-anything簡介 segment-anything是facebookresearch團隊開…