[網絡入侵AI檢測] 純卷積神經網絡(CNN)模型 | CNN處理數據

第5章:純卷積神經網絡(CNN)模型

歡迎回來

在第1章:分類任務配置(二分類 vs. 多分類)中,我們學習了如何提出正確的問題;

在第2章:數據加載與預處理中,我們準備好了數據"食材";

在第3章:經典機器學習模型中,我們探索了傳統工具;

在第4章:深度前饋神經網絡(DNN)模型中,我們首次使用多層神經網絡深入研究了深度學習

DNN非常擅長發現復雜模式,但想象一下,如果安全專家不只是查看單個特征,而是嘗試在事件流中發現特定的序列或形狀

例如,某些網絡標志的快速連續出現可能表明掃描攻擊,而較慢、更謹慎的模式則暗示另一種入侵類型

這正是純卷積神經網絡(CNN)模型的用武之地

雖然CNN以圖像識別(檢測邊緣、形狀和物體)而聞名,但它們也非常擅長在數據序列中發現局部模式,即使這些數據不是圖像。

在我們的網絡入侵檢測(NID)項目中,CNN就像專門的"模式檢測器",在做出決策前系統地掃描網絡流量特征中的重要局部序列或"簽名"。

CNN解決了什么問題?

CNN旨在直接從輸入數據中自動學習層次化特征和模式。

與DNN平等對待每個輸入特征并一次性混合它們不同,CNN使用"過濾器"掃描數據,首先挑選出小的特定模式,然后將這些小模式組合成更大、更復雜的模式。

我們使用CNN的核心用例是從41個網絡特征序列(來自第2章:數據加載與預處理的input_shape=(41, 1))中自動提取這些局部有意義的模式,將網絡連接分類為"正常"或"攻擊"(二分類),或精確定位"攻擊類型"(多分類)。它們特別擅長發現可能出現在特征序列中任何位置的"簽名"。

CNN的關鍵概念

純卷積神經網絡(針對我們的一維網絡數據)主要使用三種類型的層:卷積層、池化層,然后是展平后的密集

讓我們分解這些核心部分:

1. 卷積層(Conv1D):模式檢測器

這是CNN的核心。

  • 過濾器(核):想象一個小的"放大鏡"或迷你模式檢測器。這個過濾器是一個小窗口,在輸入數據(我們的41個特征)上滑動。當它滑動時,它會與看到的數字進行數學運算(卷積),尋找特定模式。例如,一個過濾器可能被訓練來檢測數據中的"尖峰",另一個可能尋找"低谷"。
  • 特征圖:卷積層的輸出。每個過濾器創建自己的"特征圖",顯示它在輸入數據中檢測到其特定模式的位置。如果一個過濾器擅長檢測"尖峰",其特征圖將在發現尖峰的地方有高值。
  • 1D卷積:由于我們的網絡數據是41個特征的序列,我們使用Convolution1D。這意味著我們的"放大鏡"沿單一維度滑動,掃描我們的特征序列。
  • activation='relu':就像在DNN中一樣,在卷積之后應用relu激活(第4章:深度前饋神經網絡(DNN)模型)以引入非線性,使模型能夠學習復雜關系。

2. 池化層(MaxPooling1D):總結器

在卷積層檢測到模式后,池化層有助于簡化信息并使模型更魯棒。

  • 下采樣MaxPooling1D層通過在特征圖上滑動窗口并取每個窗口中的最大值來工作。這有效地縮小了特征圖,減少了數據量,同時保留了最重要的信息(最強的模式檢測)。
  • 魯棒性:通過取最大值,它使模型對模式的確切位置不那么敏感。如果"尖峰"模式稍微移動,MaxPooling層仍然可能捕捉到它的存在。
  • pool_length:這定義了池化層使用的窗口大小。pool_length為2意味著它查看2個值的組并選擇最大的。

3. 展平層:為決策做準備

卷積和池化層以"網格狀"或"序列狀"格式(例如[samples, new_length, new_features])輸出數據。然而,做出分類決策的最終密集(全連接)層需要一個簡單的數字扁平列表。

  • 展平層完全如其名:它將卷積/池化層的3D輸出"展平"為一個長的1D向量(就像展開地毯)。這為數據輸入標準密集分類層做好準備。

4. 密集層:最終分類器

展平層之后,我們添加一個或多個密集層,就像在DNN中一樣(第4章:深度前饋神經網絡(DNN)模型)。這些層利用卷積和池化層提取的抽象特征做出最終分類決策。

5. Dropout層:防止過擬合

與DNN一樣,添加Dropout層(第4章:深度前饋神經網絡(DNN)模型)以防止模型對訓練數據記憶得太好。這確保它可以泛化到新的、未見過的網絡流量

如何構建用于入侵檢測的純CNN

我們將使用Keras構建我們的CNN。基本步驟如下:

  1. 啟動一個Sequential模型
  2. 添加Convolution1D:定義過濾器數量、核大小和激活。
  3. 添加MaxPooling1D:對特征圖進行下采樣。
  4. 添加展平:將輸出轉換為密集層。
  5. 添加密集:用于最終分類,使用relu激活。
  6. 添加Dropout:防止過擬合。
  7. 添加最終的密集輸出層:根據第1章:分類任務配置(二分類 vs. 多分類)配置為二分類或多分類。
  8. 編譯模型:定義損失函數、優化器和指標。

記住,我們的輸入數據需要重塑為[samples, time_steps, features],對于我們的KDD數據集是[number_of_connections, 41, 1]

這在第2章:數據加載與預處理中已經介紹過。

讓我們看一個簡化示例。假設X_train包含我們歸一化和重塑的網絡特征,y_train包含標簽,如第2章和第1章所述。

示例代碼:用于二分類的簡單CNN

以下是構建一個帶有一個卷積塊的基本CNN用于二分類入侵檢測的方法:

from keras.models import Sequential
from keras.layers import Convolution1D, MaxPooling1D, Flatten, Dense, Dropout
import numpy as np # 用于數據創建示例# --- 假設 X_train 和 y_train 已準備好并重塑 ---
# 為了演示,我們創建一些虛擬數據(1000個樣本,41個時間步,每個1個特征)
X_train_dummy = np.random.rand(1000, 41, 1)
y_train_dummy = np.random.randint(0, 2, 1000) # 二分類標簽# 1. 開始定義網絡(層的堆疊)
model = Sequential()# 2. 添加第一個卷積層
#    - 64個過濾器:64個不同的小模式檢測器
#    - kernel_size=3:每個過濾器一次查看3個連續特征
#    - activation='relu':如前所述
#    - input_shape=(41, 1):告訴Keras我們的輸入形狀(41個時間步,每個時間步1個特征)
model.add(Convolution1D(64, 3, activation="relu", input_shape=(41, 1)))# 3. 添加一個最大池化層
#    - pool_size=2:在2的窗口上取最大值
model.add(MaxPooling1D(pool_size=2))# 4. 展平輸出以用于密集層
model.add(Flatten())# 5. 添加一個密集層(全連接)進行更多處理
#    - 128個神經元
#    - activation='relu'
model.add(Dense(128, activation="relu"))# 6. 添加一個Dropout層以防止過擬合
#    - 0.5表示訓練期間隨機關閉50%的神經元
model.add(Dropout(0.5))# 7. 添加輸出層(用于二分類,如第1章所述)
#    - 1個神經元用于二分類輸出
#    - activation='sigmoid':將輸出壓縮為0到1之間的概率
model.add(Dense(1, activation="sigmoid"))# 8. 編譯模型
#    - loss='binary_crossentropy':用于二分類
#    - optimizer='adam':流行的優化算法
#    - metrics=['accuracy']:跟蹤性能
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=['accuracy'])print("CNN模型創建并編譯完成!")
model.summary() # 打印模型層和參數的摘要

解釋:

  • Sequential():初始化我們的模型為層的堆疊。
  • Convolution1D(64, 3, activation="relu", input_shape=(41, 1)):這是第一層。它使用64個過濾器,每個查看3個相鄰特征的窗口。input_shape對第一層至關重要。
  • MaxPooling1D(pool_size=2):該層通過保留最重要的信息(最強的模式檢測)來減小特征圖的大小。
  • Flatten():這將卷積/池化層的輸出準備好用于后續的常規密集層。
  • Dense(128, activation="relu"):一個標準的隱藏層,用于進一步處理展平的特征。
  • Dropout(0.5):幫助防止模型過擬合。
  • Dense(1, activation="sigmoid"):用于二分類的最終輸出層,給出0到1之間的概率。
  • model.compile(...):使用適當的損失函數和優化器配置模型進行訓練。

擴展到多個卷積塊和多分類

通過堆疊更多的Convolution1DMaxPooling1D塊,可以使CNN"更深"。對于多分類,只有輸出層和損失函數會改變,如第1章:分類任務配置(二分類 vs. 多分類)所述。

from keras.models import Sequential
from keras.layers import Convolution1D, MaxPooling1D, Flatten, Dense, Dropout
# ...(數據準備和重塑如前所述)...# 多分類示例:假設 num_classes = 5(正常、DoS、Probe、R2L、U2R)
num_classes = 5
# y_train_dummy 應為 one-hot 編碼,例如 to_categorical(y_train_raw, num_classes=5)model_multiclass_deep_cnn = Sequential()
# 第一個卷積塊
model_multiclass_deep_cnn.add(Convolution1D(64, 3, activation="relu", input_shape=(41, 1)))
model_multiclass_deep_cnn.add(MaxPooling1D(pool_size=2))# 第二個卷積塊(更深的網絡)
model_multiclass_deep_cnn.add(Convolution1D(128, 3, activation="relu")) # 更多過濾器用于更復雜的模式
model_multiclass_deep_cnn.add(MaxPooling1D(pool_size=2))model_multiclass_deep_cnn.add(Flatten())
model_multiclass_deep_cnn.add(Dense(128, activation="relu"))
model_multiclass_deep_cnn.add(Dropout(0.5))# 對于多分類(如第1章所述):
model_multiclass_deep_cnn.add(Dense(num_classes, activation="softmax"))model_multiclass_deep_cnn.compile(loss="categorical_crossentropy", optimizer="adam", metrics=['accuracy'])print("\n用于多分類的深度CNN模型創建并編譯完成!")
model_multiclass_deep_cnn.summary()

多分類的關鍵區別:

  • Dense(num_classes, activation="softmax"):輸出層現在有num_classes(例如5)個神經元,softmax激活確保輸出是每個類的概率,總和為1。
  • loss="categorical_crossentropy":當標簽是one-hot編碼時(多分類問題中應該如此),這是合適的損失函數。

幕后:CNN如何處理數據

將CNN想象為一個專業的安全團隊。

首先,有許多初級官員(Convolution1D過濾器),每個都訓練來發現特定的細節(例如"數據包的突然爆發")。然后,主管(MaxPooling1D)總結初級官員的發現,只記錄最顯著的檢測。這個過程重復進行,更高級別的官員(Convolution1D層)尋找這些總結細節的更復雜組合。最后,所有總結的發現交給首席分析師(展平密集層)做出最終決定。

在這里插入圖片描述

在訓練期間,這個流程會反復進行。每次傳遞后,模型將其預測與真實標簽進行比較,計算loss,然后微妙地調整內部參數(過濾器的權重、密集層)以嘗試在下一次減少loss

深入項目代碼參考

讓我們看看實際項目代碼文件,了解純CNN是如何實現的。你可以在KDDCup 99/CNN/文件夾(以及NSL-KDD、UNSW-NB15等其他數據集的類似文件夾)中找到這些內容。

1. 簡單CNN(1個卷積+池化塊)- 二分類

查看KDDCup 99/CNN/binary/cnn1.pyNSL-KDD/CNN/binary/cnn1.py。在數據加載、歸一化和重塑步驟(如第2章:數據加載與預處理所述)之后:

# 來自 KDDCup 99/CNN/binary/cnn1.py(簡化版)
from keras.models import Sequential
from keras.layers import Convolution1D, MaxPooling1D, Flatten, Dense, Dropout
import numpy as np # 用于np.reshape(如果尚未導入)# ...(X_train, y_train, X_test, y_test 已準備好并重塑)...cnn = Sequential()
# 卷積層:64個過濾器,核大小3,relu激活,輸入形狀(41,1)
cnn.add(Convolution1D(64, 3, border_mode="same", activation="relu", input_shape=(41, 1)))
# 池化層:池長度2
cnn.add(MaxPooling1D(pool_length=(2)))
# 展平層
cnn.add(Flatten())
# 密集層:128個神經元,relu激活
cnn.add(Dense(128, activation="relu"))
# Dropout層:0.5(50%)的丟棄率
cnn.add(Dropout(0.5))
# 輸出層:1個神經元,用于二分類的sigmoid激活
cnn.add(Dense(1, activation="sigmoid"))print(cnn.summary()) # 查看模型的架構
# cnn.compile(...) # 編譯代碼在原代碼片段中被注釋掉

觀察:

  • input_shape=(41, 1)正確指定了第一個Convolution1D層的輸入維度。
  • Convolution1D中的border_mode="same"意味著輸出特征圖將與輸入長度相同,必要時填充邊緣。
  • Convolution1DMaxPooling1DFlattenDenseDropout和最終Dense層的堆疊構成了完整的CNN。
  • 輸出層(Dense(1, activation="sigmoid"))和相關的binary_crossentropy損失(在注釋掉的編譯部分中)與我們在第1章中的二分類設置一致。

2. 更深CNN(多個卷積+池化塊)- 二分類

現在,我們來看KDDCup 99/CNN/binary/cnn3.py。這個文件通過堆疊更多的卷積和池化層展示了"更深"的CNN:

# 來自 KDDCup 99/CNN/binary/cnn3.py(簡化版)
from keras.models import Sequential
from keras.layers import Convolution1D, MaxPooling1D, Flatten, Dense, Dropout# ...(X_train, y_train, X_test, y_test 已準備好并重塑)...cnn = Sequential()
# 第一個卷積塊
cnn.add(Convolution1D(64, 3, border_mode="same", activation="relu", input_shape=(41, 1)))
cnn.add(Convolution1D(64, 3, border_mode="same", activation="relu")) # 另一個Conv1D
cnn.add(MaxPooling1D(pool_length=(2)))
# 第二個卷積塊
cnn.add(Convolution1D(128, 3, border_mode="same", activation="relu")) # 更多過濾器用于更復雜的模式
cnn.add(Convolution1D(128, 3, border_mode="same", activation="relu"))
cnn.add(MaxPooling1D(pool_length=(2)))
# 展平和密集層用于分類
cnn.add(Flatten())
cnn.add(Dense(128, activation="relu"))
cnn.add(Dropout(0.5))
cnn.add(Dense(1, activation="sigmoid"))# cnn.compile(...) # 編譯代碼
# cnn.fit(...) # 訓練代碼

觀察:

  • 這個模型使用了兩個Convolution1D層后跟一個MaxPooling1D層,然后用更多過濾器(128而不是64)重復這個模式。這使得網絡能夠學習逐漸更復雜和抽象的模式。
  • 過濾器的數量通常在更深的層中增加,因為它們學習將更簡單的特征組合成更復雜的特征。
  • 輸出層和損失函數與cnn1.py相同,因為它仍然是二分類任務。

3. 簡單CNN(1個卷積+池化塊)- 多分類

最后,我們來看KDDCup 99/CNN/multiclass/cnn1.py。它使用類似的CNN結構,但適應了多分類:

# 來自 KDDCup 99/CNN/multiclass/cnn1.py(簡化版)
from keras.models import Sequential
from keras.layers import Convolution1D, MaxPooling1D, Flatten, Dense, Dropout
from keras.utils.np_utils import to_categorical # 用于標簽準備
import numpy as np# ...(X_train, y_train1, X_test, y_test1 已準備好)...
# 數據準備:對多分類標簽進行one-hot編碼
y_train = to_categorical(y_train1)
y_test = to_categorical(y_test1)cnn = Sequential()
# 卷積和池化層保持不變用于特征提取
cnn.add(Convolution1D(64, 3, border_mode="same", activation="relu", input_shape=(41, 1)))
cnn.add(MaxPooling1D(pool_length=(2)))
cnn.add(Flatten())
cnn.add(Dense(128, activation="relu"))
cnn.add(Dropout(0.5))
# 輸出層:5個神經元(用于5個類別),softmax激活
cnn.add(Dense(5, activation="softmax"))# cnn.compile(...) # 編譯代碼
# cnn.fit(...) # 訓練代碼

觀察:

  • 關鍵的是,y_trainy_test標簽在輸入模型前使用to_categorical(one-hot編碼)轉換,如第1章所述。
  • 特征提取部分(Convolution1DMaxPooling1D層)與二分類版本相同。
  • 輸出層使用Dense(5)(假設多分類數據集中有5個類別)和activation="softmax"
  • 損失函數現在是categorical_crossentropy,適用于one-hot編碼標簽。

這些示例清楚地展示了使用Convolution1DMaxPooling1D層提取模式是CNN的核心,而輸出層和損失函數則根據具體分類任務進行調整。

結論

現在,已經了解了純卷積神經網絡(CNN)模型在網絡入侵檢測中的基礎知識

理解了Convolution1D層如何作為模式檢測器,MaxPooling1D層如何總結這些檢測,以及展平層如何將這些見解準備好用于傳統的密集分類層。你還看到了如何使用Keras構建這些模型,并為二分類和多分類入侵檢測任務配置它們,這些建立在前面章節的基礎知識之上。

CNN在自動學習網絡流量特征中的"簽名"方面非常有效,這對于發現復雜和不斷演變的威脅至關重要。

接下來,我們將探索另一種強大的深度學習模型:循環神經網絡(RNN)。雖然CNN擅長發現局部模式,但RNN設計用于記住較長序列中的信息,這對于理解網絡流量的時間性質特別有用。

第6章:循環神經網絡(RNN)模型(LSTM/GRU/SimpleRNN)

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

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

相關文章

Unity AssetBundle詳解

簡介 AssetBundle(簡稱:AB包) 是 Unity 提供的一種資源壓縮包,用于在應用運行時動態地加載和卸載資源。它可以將非代碼資源(如模型、紋理、預制體、音頻、甚至整個場景)打包成一個或多個文件,這…

golang-gin包

文章目錄一、了解gin二、html渲染三、gin中get/post獲取值四、路由分組五、中間件六、文件上傳七、gin中的cookie一、了解gin Gin 是一個用 Golang編寫的 高性能的web 框架, 由于http路由的優化,速度提高了近 40 倍。 Gin的特 點就是封裝優雅、API友好。 特性類別…

基于腳手架微服務的視頻點播系統-界面布局部分(二):用戶界面及系統管理界面布局

基于腳手架微服務的視頻點播系統-界面布局部分:二.首頁及播放界面布局一.用戶界面布局1.1用戶界面布局分析與實現1.2更新用戶圖像按鈕及邏輯1.3修改按鈕及邏輯1.4上傳視頻對話框實現邏輯1.4.1頁面跳轉邏輯處理1.4.2頁面控件響應處理二.系統界面布局2.1系統管理頁框架2.2審核管理…

STL庫——二叉搜索樹

? ? ? ? ? づ?ど 🎉 歡迎點贊支持🎉 個人主頁:勵志不掉頭發的內向程序員; 專欄主頁:C語言; 文章目錄 前言 一、二叉搜索樹的概念 二、二叉搜索樹的性能分析 三、二叉搜索樹的插入 四、二叉搜索樹的查…

【Linux】線程概念與控制

一. 線程的概念1.什么是線程線程是進程內部的一個執行流,是進程調度的基本單位。它具有輕量的特點,它的創建和銷毀所消耗的資源更少,線程間切換比進程間切換消耗的資源更少;它與進程共享一張虛擬地址空間表,通過進程來…

雙軸傾角傳感器廠家與物聯網角度傳感器應用全解析

本文主要探討雙軸傾角傳感器廠家的核心技術優勢,以及物聯網角度傳感器在智能監測中的創新應用。同時,也詳細介紹了水平監測傳感器廠家的解決方案特點,并分析了專業進口傾角傳感器代理所提供的原廠品質保障與本地化服務支持。以深圳瑞慣科技有…

容器-資源隔離機制

一. 引言: 大家都知道,在一臺機器上,可以運行任意(根據系統資源)個容器實例。且各容器間是相互獨立,不做任何關聯的。那么,docker是通過什么方式來實現容器隔離的呢? 接下來我們了解下。 二. 關于容器隔離…

Agentic RL Survey: 從被動生成到自主決策

Agentic RL Survey: 從被動生成到自主決策 本文將系統解讀《The Landscape of Agentic Reinforcement Learning for LLMs: A Survey》這篇綜述。該綜述首次將智能體強化學習(Agentic RL)與傳統LLM-RL范式正式區分,通過MDP/POMDP理論框架梳理…

徹底禁用 CentOS 7.9 中 vi/vim 的滴滴聲

在 VMware 虛擬機中安裝的 CentOS 7.9 系統,即使通過修改 /etc/inputrc 禁用了終端鈴聲(set bell-style none),vi 或 vim 編輯時仍可能發出滴滴聲。這是因為 vi/vim 有自己獨立的鈴聲控制機制。以下是解決方法:方法 1&…

基于A2A和ADK的內容規劃代理

項目概述 Content Planner Agent 是一個基于 Google Agent Development Kit (ADK) 和 Python A2A SDK 構建的智能內容規劃代理。該代理能夠根據高層次的內容描述,創建詳細的內容大綱。 什么是A2A Protocol A2A Protocol(Agent2Agent 協議)…

Linux-條件變量

文章目錄條件變量概述條件變量的優缺點條件變量相關函數pthread_cond_init函數pthread_cond_destroy函數pthread_cond_wait函數pthread_cond_signal函數測試生產者和消費者模型條件變量 概述 與互斥鎖不同,條件變量是用來等待而不是用來上鎖的,條件變量…

[硬件電路-166]:Multisim - SPICE與Verilog語言的區別

SPICE與Verilog語言在電子設計領域中扮演不同角色,SPICE是電路仿真語言,用于精確模擬電路行為;Verilog是硬件描述語言,用于描述數字電路的結構和行為。以下是兩者的詳細區別:一、核心定位與用途SPICE:電路仿…

玩轉Docker | 使用Docker部署Umbrel操作系統

玩轉Docker | 使用Docker部署Umbrel操作系統 前言 一、 Umbrel 介紹 Umbrel簡介 Umbrel主要特點 二、系統要求 環境要求 環境檢查 Docker版本檢查 檢查操作系統版本 三、部署Umbrel服務 下載Umbrel鏡像 編輯部署文件 創建容器 檢查容器狀態 檢查服務端口 安全設置 四、訪問Umbr…

Flink Task線程處理模型:Mailbox

Task的線程 和 MailboxProcessor 的綁定executingThread 是 Task 類(StreamTask 的父類)在構造時創建的物理線程。MailboxProcessor 是 StreamTask 用來處理異步事件和驅動其主要處理邏輯(processInput)的核心組件。它們之間的綁定…

OpenCV 銀行卡號識別

目錄 一、項目原理與核心技術 二、環境準備與工具包導入 1. 環境依賴 2. 工具包導入 三、自定義工具類 myutils.py 實現 四、主程序核心流程(銀行卡識別.py) 1. 命令行參數設置 2. 銀行卡類型映射 3. 輔助函數:圖像展示 五、步驟 1…

計算機二級Python

一.靜態語言和腳本語言高級語言根據計算機執行機制的不同分為兩類:靜態語言和腳本語言靜態語言的核心特征:變量的類型在編譯時(寫代碼時)就必須確定并固定下來,即在使用一個變量前必須顯式地聲明它地類型一旦聲明&…

Mybatis Log Plugin打印日志,會導致CPU升高卡死

原因 大量日志輸出:MyBatis Log Plugin 會打印大量的 SQL 日志,包括 SQL 語句及其參數。如果項目中 SQL 查詢頻繁且復雜,日志量會非常大,導致 CPU 使用率升高,甚至卡死。 日志級別設置不當:如果將日志級別設置為 DEBUG 或 TRACE,MyBatis 會輸出非常詳細的日志信息,這會…

鴻蒙:深色模式適配和淺色模式的切換

前言: 有些時候我們需要對應用進行深色模式的適配處理,并且在不需要的時候切換到淺色狀態,下面和大家一起照著官方文檔來學習。 下面是官方文檔的鏈接: https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-dark-…

Coze源碼分析-資源庫-刪除插件-后端源碼-數據訪問和基礎設施層

5. 數據訪問層 5.1 倉儲接口定義 插件倉儲接口 文件位置:backend/domain/plugin/repository/plugin.go type PluginRepository interface {// DeleteDraftPlugin 刪除插件草稿DeleteDraftPlugin(ctx context.Context, pluginID int64) error// DeleteAPPAllPlugins …

案例一: 對基礎選擇器的使用【網頁盒子】

【1】樣例&#xff1a;首先&#xff0c;觀察到&#xff0c;幾個元素豎著排列的&#xff0c;所以使用塊級元素&#xff0c;而不是行內元素。【2】代碼演示<head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,…