上期填坑
leetcode,16.25. LRU 緩存
設計和構(gòu)建一個“最近最少使用”緩存,該緩存會刪除最近最少使用的項目。
緩存應該從鍵映射到值(允許你插入和檢索特定鍵對應的值),并在初始化時指定最大容量。當緩存被填滿時,它應該刪除最近最少使用的項目。
它應該支持以下操作: 獲取數(shù)據(jù) get 和 寫入數(shù)據(jù) put 。
獲取數(shù)據(jù) get(key) - 如果密鑰 (key) 存在于緩存中,則獲取密鑰的值(總是正數(shù)),否則返回 -1。
寫入數(shù)據(jù) put(key, value) - 如果密鑰不存在,則寫入其數(shù)據(jù)值。
當緩存容量達到上限時,它應該在寫入新數(shù)據(jù)之前刪除最近最少使用的數(shù)據(jù)值,從而為新的數(shù)據(jù)值留出空。
public class LRUCache {
class DLinkedNode {//定義雙向鏈表節(jié)點和構(gòu)造函數(shù)
int key;
int value;
DLinkedNode prev;
DLinkedNode next;
public DLinkedNode() {}
public DLinkedNode(int _key, int _value) {key = _key; value = _value;}
}
//使用hash進行快速定位節(jié)點
private Map<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();
private int size;
private int capacity;
private DLinkedNode head, tail;
//初始化
public LRUCache(int capacity) {
this.size = 0;
this.capacity = capacity;
// 使用偽頭部和偽尾部節(jié)點
head = new DLinkedNode();
tail = new DLinkedNode();
head.next = tail;
tail.prev = head;
}
public int get(int key) {
DLinkedNode node = cache.get(key);
if (node == null) {
return -1;
}
// 如果 key 存在,先通過哈希表定位,再移到頭部
moveToHead(node);
return node.value;
}
public void put(int key, int value) {
DLinkedNode node = cache.get(key);
if (node == null) {
// 如果 key 不存在,創(chuàng)建一個新的節(jié)點
DLinkedNode newNode = new DLinkedNode(key, value);
// 添加進哈希表
cache.put(key, newNode);
// 添加至雙向鏈表的頭部
addToHead(newNode);
++size;
if (size > capacity) {
// 如果超出容量,刪除雙向鏈表的尾部節(jié)點
DLinkedNode tail = removeTail();
// 刪除哈希表中對應的項
cache.remove(tail.key);
--size;
}
}
else {
// 如果 key 存在,先通過哈希表定位,再修改 value,并移到頭部
node.value = value;
moveToHead(node);
}
}
//偽頭節(jié)點的作用是為了快速頭插
private void addToHead(DLinkedNode node) {
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
private void removeNode(DLinkedNode node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void moveToHead(DLinkedNode node) {
removeNode(node);
addToHead(node);
}
private DLinkedNode removeTail() {
DLinkedNode res = tail.prev;
removeNode(res);
return res;
}
}

ComfyUI
ComfyUI是鼎鼎大名的Stable Diffusion圖像生成模型的使用界面之一。相比于其前輩WebUI,ComfyUI不僅在組織形式上,在性能上也得到了提升:
? 以工作流形式面向用戶,給用戶更高的自由度,直觀易用。
? 功能模塊節(jié)點化,用戶更加清楚功能和數(shù)據(jù)流轉(zhuǎn),可根據(jù)需求定制化
? 性能優(yōu)化,圖片生成速度更快
? 內(nèi)部流程優(yōu)化,硬件要求更低,低顯存和CPU也能運行,降低使用門檻
? 支持工作流程分享
ComfyUI 開源地址:https://github.com/comfyanonymous/ComfyUI
Web UI 開源地址:https://github.com/AUTOMATIC1111/stable-diffusion-webui
Stable diffusion 開源地址:https://github.com/CompVis/stable-diffusion
ComfyUI功能強大,包括文生圖、圖生圖、文生視頻、圖片修復等,這里以文生圖來對ComfyUI進行詳細的入門介紹。
ComfyUI安裝
windows下載安裝:
對于windows用戶來說只需要上ComfyUI的GitHub開源地址下載壓縮包即可,如下圖:

解壓安裝包到合適位置(建議選擇磁盤剩余空間大的盤),如下圖,

ComfyUI提供了run_cpu和run_nvida_gpu兩種啟動腳本,顧名思義,分別為使用CPU和GPU運算,選擇響應的文件雙擊即啟動。
Llinux、mac安裝啟動
需要按照ComfyUI的GitHub開源地址中說明,依次
克隆項目:
git clone https://github.com/comfyanonymous/ComfyUI.git
安裝環(huán)境:
AMD :pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.0
NVIDA:pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu121
安裝依賴:
pip install -r requirements.txt
手動運行python main.py 啟動。
ComfyUI啟動界面如下如:

模型安裝
ComfyUI已經(jīng)啟動,但是沒有模型來運行,需要我們下載模型到對應的目錄中,如圖:

提供兩個下載模型資源的地址:
抱抱臉:https://huggingface.co/
C站:https://civitai.com/
我在https://huggingface.co/runwayml/stable-diffusion-v1-5 下載v1-5-pruned-emaonly.ckpt模型后,放入checkpoint目錄,啟動程序,選擇好模型,使用默認的提示詞、參數(shù)、解碼器等,運行的效果如圖:

模塊詳解
以默認的文生圖流程為例,對ComfyUI的各個流程節(jié)點:大模型加載器、正向提示詞、反向提示詞、采樣器、圖像寬高、輸出輸出、VAE解碼器等進行介紹。
模型加載器
如下圖,模型加載器分為幾大類,分別是模型庫(checkpoint),插件預訓練模型(VAE、LoRA等),放大器(upscale)等。

按照如圖選擇的路徑點擊,即可添加大模型的加載器節(jié)點,如圖所示:

本地已加載4個大模型供選擇,雙擊即可選擇。
正反提示詞
提示詞在文生圖中至關(guān)重要,提示詞的好壞關(guān)系到生成的圖的效果。 如果自己運行文生圖時,可以借鑒C站相關(guān)做作品的提示詞模版。 提示詞節(jié)點如下圖方法添加:

一個輸入CLIP剛好與大模型的輸出CLIP可以相連,一個輸出與采樣器相連。 你會發(fā)現(xiàn)ComfyUI將可以相連的顏色也進行了匹配。
圖像屬性
如圖添加圖像屬性:寬和高,batch_size指一次生產(chǎn)圖的數(shù)量。僅有一個輸出。

采樣器
如圖,我們添加簡單的采樣器:

4個輸入:分別對應大模型的model輸出、正反提示詞和圖像屬性。
一個輸出:流程經(jīng)過采樣器處理完成后,圖像在低維度意味著已經(jīng)生產(chǎn),所以最后要連接VAE解碼器進行解碼。

采樣器的7個參數(shù):
? seed:種子,每張圖都有個隨機的種子。
? control_after_generate:每次生產(chǎn)圖后下一次種子的產(chǎn)生方式。默認是隨機。
注:當我們要微調(diào)當前已生產(chǎn)的圖像時,將這個選項設置為固定。這樣生成的圖像不會相差太大。
? steps:生產(chǎn)圖需要去噪的次數(shù),值越大,圖像越清晰,當然運行越慢。
? cfg:提示詞在生成中的權(quán)重,越小生成的圖越與提示詞風馬牛不相及,一般0.8~0.9.
? samper_name:ComfyUI提供了多種不同的采樣器供選擇,每種有不同的效果。感興趣可以一一對比。
? scheduler:控制迭代中噪聲量大小,也有多種可選。
? denoise:與steps相關(guān),1表示按照steps設置的步數(shù)去降噪。
VAE解碼器
如圖進行添加。

輸入samples與采樣器的輸入相連。VAE直接與大模型的VAE相連。我們也可以新建一個VAE加載器與其相連,自定義要用的加載器類型。
輸入圖像直接與圖像現(xiàn)實/保存相連。
保存圖像
如圖進行添加:

保存圖像也有
預覽的功能,如果只是想預覽圖像可以選擇添加preview image節(jié)點。保存圖像
默認的保存路徑在ComfyUI安裝路徑的output目錄下。
生成圖像
添加好節(jié)點,只需選好要連接的輸入輸出,拖動就可以連接。 ComfyUI的顏色匹配可以輔助。
點擊如下圖,控制面板的Queue Prompt或者按下Ctrl + enter,即可運行。

流程圖運行過程中會標識運行的進度,表示正在運行的節(jié)點,清晰直觀。
運行結(jié)束,可以save我們的流程圖,以便下次加載或分享給他人。
如下git圖,拖動連接各個節(jié)點及點擊生成圖過程:

接下就可以自己設置相關(guān)變量參數(shù),試試看了。 如下圖是我參照C站相關(guān)作品的參數(shù),生成流程圖:

每日一算
leetcode , 209. 長度最小的子數(shù)組
給定一個含有 n 個正整數(shù)的數(shù)組和一個正整數(shù) target 。 找出該數(shù)組中滿足其總和大于等于 target 的長度最小的子數(shù)組 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其長度。如果不存在符合條件的子數(shù)組,返回 0 。