SEW:無監督預訓練在語音識別中的性能-效率權衡

摘要

本文研究了自動語音識別(ASR)中預訓練模型的性能-效率權衡問題。我們聚焦于 wav2vec 2.0,并形式化了多種影響模型性能和效率的架構設計。基于所有觀察結果,我們提出了 SEW(Squeezed and Efficient Wav2vec)這一預訓練模型架構,在多種訓練設置中在性能和效率兩個維度上都取得了顯著改進。例如,在 LibriSpeech 的 100h-960h 半監督設置下,SEW 相比 wav2vec 2.0 實現了 1.9 倍的推理速度提升,同時詞錯誤率相對降低了 13.5%。在相似的推理時間下,SEW 在不同模型規模下將詞錯誤率降低了 25–50%。

1. 引言

近年來,利用無標簽音頻數據進行自監督預訓練,以學習通用特征表示的研究受到廣泛關注,這些特征隨后會在特定任務的標注音頻上進行微調(Zhang et al., 2020b;Wang et al., 2021b;Xu et al., 2020a;Pepino et al., 2021)。這一趨勢與自然語言處理(NLP;Devlin et al., 2018;Liu et al., 2019;He et al., 2020)和計算機視覺(CV;He et al., 2019;Chen et al., 2020;Grill et al., 2020)中的發展類似。其中最具代表性的模型可能就是 wav2vec 2.0(W2V2;Baevski et al., 2020b),該模型在僅使用十分鐘轉錄(有標簽)數據進行微調后,便可實現有競爭力的詞錯誤率(WER),而以往的監督方法通常需要近千小時的標注數據。如果 NLP 和 CV 的最新進展具有參考價值,那么這些可以在專業任務上微調的預訓練音頻模型的重要性只會愈加顯著。實際上,已有研究聚焦于 W2V2 的預訓練數據(Conneau et al., 2020;Hsu et al., 2021)、預訓練任務(Hsu et al., 2020)或與偽標簽方法結合的效果(Xu et al., 2020a;Zhang et al., 2020b)。

在本文中,我們研究了 W2V2 的模型設計,以及其各組成部分之間可能存在的權衡關系。我們的重點是模型在實際應用中的效率,而非對模型結構的擴展。隨著 W2V2 類模型日益普及,理解其效率權衡對于將這些成果從實驗室推廣到現實世界尤為關鍵,在現實場景中,效率的任何提升都可能顯著降低推理成本和能耗開銷,進而影響大量實際應用。
在這里插入圖片描述

我們從多個方面對 W2V2 模型進行了研究,重點關注自動語音識別(ASR),同時保留標準的預訓練和少樣本微調設置。首先,我們研究了網絡的時間分辨率如何在性能與效率之間進行權衡,結果表明,在計算預訓練表示和進行 ASR 解碼時采用不同的分辨率,可以顯著減少推理時間,同時保持類似的性能。其次,我們提出了一組高效的波形特征提取器,其性能與原始 W2V2 提取器相當,但推理時間僅為原來的二分之一。最后,我們研究了在網絡不同部分之間重新分配模型表達能力的影響。我們發現,將更多參數分配給預訓練網絡的后部比增加靠近輸入波形的容量效果更好。我們還觀察到,提高預訓練階段預測頭(predictor heads)的表達能力能提升性能,而不會影響下游任務的計算開銷,因為這些頭在下游使用中會被丟棄。

基于上述觀察,我們提出了兩個模型:SEW(Squeezed and Efficient Wav2vec)和SEW-D(引入解耦注意力機制的 SEW,He et al., 2020)。我們在 LibriSpeech 數據集(Panayotov et al., 2015)的 960 小時無標簽音頻上對 SEW 和 SEW-D 進行了預訓練,并在多個 ASR 任務上進行微調。SEW 在性能-效率權衡方面明顯優于原始的 W2V2。例如,在使用 100 小時有標簽數據的情況下,相比 W2V2-tiny 模型,SEW 將 LibriSpeech test-clean 的詞錯誤率(WER)從 22.8% 降低到 10.6%,同時略快于后者,甚至優于一個較大的 W2V2 模型(其 WER 為 12.8%)。與官方發布的 W2V2-large 模型相比,我們最好的 SEW-D-base+ 在推理和預訓練中分別實現了 2.7× 和 3.2× 的加速,同時在參數數量減半的情況下保持了相近的 WER。與 W2V2-base 相比,我們的 SEW-D-mid 實現了 1.9× 的推理速度提升,并將 WER 相對降低了 13.5%。

圖 1 展示了不同模型規模下的性能-效率權衡結果。在對 LibriSpeech(Panayotov et al., 2015)、Ted-lium 3(Hernandez et al., 2018)、VoxPopuli(Wang et al., 2021a)和 Switchboard(Godfrey and Holliman, 1993)數據集進行實驗時,SEW-D 在大多數預訓練設置下都優于 W2V2。預訓練模型和代碼已開源,地址為:https://github.com/asappresearch/sew

2 相關工作

無監督音頻表示學習
對比預測編碼(Contrastive Predictive Coding, CPC)是一種通用的無監督學習方法,適用于語音、視覺、文本以及強化學習等任務(van den Oord et al., 2018)。在語音任務中,CPC 使用過去的音頻來預測未來的音頻,類似于語言建模(Mikolov et al., 2010;Dauphin et al., 2017;Kaplan et al., 2020),但使用的是對比損失函數。Wav2vec(Schneider et al., 2019)在 CPC 模型結構的基礎上進行了改進,專注于為端到端自動語音識別提供無監督預訓練。大致來說,wav2vec 包含一個從原始波形音頻中提取特征向量序列的特征提取器,以及一個上下文網絡,該網絡對最近的特征進行編碼,用于預測接下來時刻的特征。這個上下文網絡僅用于學習有用的特征表示,通常在預訓練后會被丟棄。

近期,Baevski 等人(2020a)提出了 vq-wav2vec,并將其與一個類似 BERT 的離散模型結合(Devlin et al., 2019;Baevski et al., 2019)。W2V2(Baevski et al., 2020b)將 vq-wav2vec 與 BERT 式模型整合為一個端到端的訓練框架,在其中 BERT 模塊扮演上下文網絡的角色,但不再在預訓練后被丟棄。最近,Hsu 等人(2020)提出了 HuBERT,并展示了 W2V2 可以通過聚類目標進行預訓練,而無需使用對比目標函數。

除了專注于 ASR 的研究之外,音頻表示學習在其他語音任務(Synnaeve and Dupoux, 2016;Chung et al., 2018;Chuang et al., 2019;Song et al., 2019)、音樂(Yang et al., 2021;Zhao and Guo, 2021)以及通用音頻任務(Saeed et al., 2021;Gong et al., 2021;Niizumi et al., 2021;Wang et al., 2021c)中也引起了廣泛關注。

端到端自動語音識別(ASR)
隨著大規模數據集和高速計算資源的普及,端到端 ASR 模型(Amodei et al., 2016;Zhang et al., 2020b)逐漸達到了最先進水平,超越了基于 HMM-DNN 的混合系統(Abdel-Hamid et al., 2012;Hinton et al., 2012)。端到端 ASR 模型大致可以分為三類:連接時序分類(CTC;Graves et al., 2013)、RNN 轉導器(RNN-T;Graves, 2012;Han et al., 2020;Gulati et al., 2020)和序列到序列模型(又稱 Listen, Attend and Spell;Seq2seq;Chan et al., 2016;Dong et al., 2018;Watanabe et al., 2018)。CTC 模型在批量解碼中速度極快;RNN-T 變體常用于實時系統中;而 Seq2seq 模型則更常見于離線應用場景。

近期,隨著 Transformer 架構(Vaswani et al., 2017;Dong et al., 2018)在自然語言處理任務中取得成功,語音處理也逐步向 Transformer 及其變體(Zhang et al., 2020a;Baevski et al., 2020b;Gulati et al., 2020;Zhang et al., 2020b;Yeh et al., 2019)轉變。

3 技術背景:Wav2Vec 2.0(W2V2)

W2V2 由一個波形特征提取器和一個上下文網絡組成。波形特征提取器生成一系列連續的特征向量,每個向量編碼音頻中的一個短時間片段;上下文網絡則將這些特征向量映射為上下文相關的表示。

預掩碼特征被離散化,用作預測目標。上下文網絡的目標是在被掩碼的位置上,從一組負樣本中識別出原始特征的離散版本,使用 InfoNCE 損失函數(van den Oord et al., 2018)。圖2展示了 W2V2 的整體框架,包括 (a) 一個特征提取器、(b) 一個上下文網絡、(c)一個可選的量化模塊,以及 (d) 兩個投影頭。
在這里插入圖片描述

**Wave Feature Extractor(WFE)**波形特征提取器 f(?)f(\cdot)f(?) 對原始波形音頻輸入 X=(x1,...,xTinput)∈RTinput×dinput\mathbf { X } = ( \mathbf { x } _ { 1 } , . . . , \mathbf { x } _ { T _ { \mathrm { i n p u t } } } ) \in \mathbb { R } ^ { T _ { \mathrm { i n p u t } } \times d _ { \mathrm { i n p u t } } }X=(x1?,...,xTinput??)RTinput?×dinput? 進行編碼和下采樣(其中 dinput=1d_{\text{input}} = 1dinput?=1,表示單通道音頻),生成特征向量序列 Z=f(X)=(z1,...,zT)∈RT×Rdfeat\mathbf { Z } = f ( \mathbf { X } ) = ( z _ { 1 } , . . . , z _ { T } ) \in \mathbb { R } ^ { T \times \mathbb { R } ^ { d _ { \mathrm { f e a t } } } }Z=f(X)=(z1?,...,zT?)RT×Rdfeat?。例如,W2V2 使用卷積型 WFE 將 16KHz 音頻序列映射為 50Hz 的幀,其感受野大小為 400,步長為 320。每個特征向量編碼原始信號中一個 25ms(即 1000/16000×4001000/16000 \times 4001000/16000×400)的時間窗口,步長為 20ms(即 1000/16000×3201000/16000 \times 3201000/16000×320)。壓縮后的序列長度為 T=Tinput?400320+1=Tinput?80320T = \frac{T_{\text{input}} - 400}{320} + 1 = \frac{T_{\text{input}} - 80}{320}T=320Tinput??400?+1=320Tinput??80?

上下文網絡(Context Network)g(?)g(\cdot)g(?) 遵循與自然語言處理中的掩碼語言模型(如 BERT(Devlin et al., 2018)或 RoBERTa(Liu et al., 2019))類似的原理。在預訓練過程中,每個特征向量 ztz_tzt? 會以預定義概率 ppp 被掩碼并替換為一個可訓練的掩碼向量 mmm。例如,序列 Z=(z1,z2,z3,z4,z5,z6,...,zT)Z = (z_1, z_2, z_3, z_4, z_5, z_6, ..., z_T)Z=(z1?,z2?,z3?,z4?,z5?,z6?,...,zT?) 可能變為 Z′=(z1,m,m,z4,m,z6,...,zT)Z' = (z_1, m, m, z_4, m, z_6, ..., z_T)Z=(z1?,m,m,z4?,m,z6?,...,zT?)。上下文網絡將這個掩碼后的序列映射為上下文相關表示序列 C=g(Z′)=(c1,...,cT)∈RT×dfeatC = g(Z') = (c_1, ..., c_T) \in \mathbb{R}^{T \times d_{\text{feat}}}C=g(Z)=(c1?,...,cT?)RT×dfeat?,以融合上下文信息。即使某個 ztz_tzt? 被掩碼替換為 mmm,我們仍期望對應的 ctc_tct? 能恢復 ztz_tzt? 的信息,因為 ctc_tct? 包含來自周圍未被掩碼輸入向量的信息。上下文網絡通常采用 Transformer 架構實現(Vaswani et al., 2017;Gulati et al., 2020)。

量化模塊(Quantization Module)q(?)q(\cdot)q(?) 將每個未掩碼的特征向量 ztz_tzt? 映射為量化形式 qt=q(zt)∈Rdfeatq_t = q(z_t) \in \mathbb{R}^{d_{\text{feat}}}qt?=q(zt?)Rdfeat?,該量化向量作為掩碼位置 ttt 的預測目標。該模塊基于帶有直通估計器的 Gumbel softmax(Gumbel, 1954;Jang et al., 2016;Maddison et al., 2014)。量化模塊由 GGG 個碼本組成,每個碼本包含 VVV 個條目,共有 G×VG \times VG×V 個向量 eg,v∈RdfeatGe_{g,v} \in \mathbb{R}^{\frac{d_{\text{feat}}}{G}}eg,v?RGdfeat??,其中 g∈{1,...,G}g \in \{1,...,G\}g{1,...,G}v∈{1,...,V}v \in \{1,...,V\}v{1,...,V}。對每個組 ggg,將 ztz_tzt? 分配到第 vvv 個條目的概率為
pg,v=exp?(Wvg?zt/τQ)∑v′=1Vexp?(Wv′g?zt/τQ)p_{g,v} = \frac{\exp(W_{vg} \cdot z_t / \tau_Q)}{\sum_{v'=1}^V \exp(W_{v'g} \cdot z_t / \tau_Q)} pg,v?=v=1V?exp(Wvg??zt?/τQ?)exp(Wvg??zt?/τQ?)?

其中 Wg∈RV×dfeatW^{g} \in \mathbb{R}^{V \times d_{\text{feat}}}WgRV×dfeat? 是可訓練矩陣,τQ\tau_QτQ? 是量化溫度。每組 gggztz_tzt? 分配給概率最大的條目 vg?=arg?max?vpg,vv_g^* = \arg\max_v p_{g,v}vg??=argmaxv?pg,v?。對應的嵌入向量 (e1,v1?,...,eG,vG?)(e_{1, v_1^*}, ..., e_{G, v_G^*})(e1,v1???,...,eG,vG???) 被連接成單一向量 qt∈Rdfeatq_t \in \mathbb{R}^{d_{\text{feat}}}qt?Rdfeat?,構成量化特征序列 Q=(q1,...,qT)∈RT×dfeatQ = (q_1, ..., q_T) \in \mathbb{R}^{T \times d_{\text{feat}}}Q=(q1?,...,qT?)RT×dfeat?

投影頭(Projection Heads)包括兩個線性投影頭 pc(?)p_c(\cdot)pc?(?)pq(?)p_q(\cdot)pq?(?),用于降低上下文表示 CCC 和量化特征 QQQ 的維度。對于被掩碼替換成 mmmztz_tzt?,希望 pc(ct)∈Rdprojp_c(c_t) \in \mathbb{R}^{d_{\text{proj}}}pc?(ct?)Rdproj?pq(qt)∈Rdprojp_q(q_t) \in \mathbb{R}^{d_{\text{proj}}}pq?(qt?)Rdproj? 彼此相似。Baevski 等人(2020b)在原始符號中未區分 pcp_cpc?gggpqp_qpq?qqq,但這里保持區分,因為它們在不同階段發揮不同作用,且在下游微調前均被舍棄。

預訓練目標 W2V2 在預訓練損失中結合了對比損失和多樣性損失:
L=Lm+αLd(1)\mathcal { L } = \mathcal { L } _ { m } + \alpha \mathcal { L } _ { d }\quad(1) L=Lm?+αLd?(1)
對比損失 LmL_mLm? 的目標是使得投影后的輸出 pc(ct)p_c(c_t)pc?(ct?)pq(qt)p_q(q_t)pq?(qt?) 接近,同時與同一序列中其他位置 t′t'tpq(qt′)p_q(q_{t'})pq?(qt?) 保持距離。W2V2 使用了 InfoNCE 損失(van den Oord et al., 2018):
Lm=Etismasked[?log?exp?(sim(pc(ct),pq(qt))/κ)∑qt′∈Qexp?(sim(pc(ct),pq(qt′))/κ)](2)\mathcal { L } _ { m } = \mathbb { E } _ { t \mathrm { \, i s \, m a s k e d } } \left[ - \log \frac { \exp ( \mathcal { sim } ( p _ { c } ( c _ { t } ) , p _ { q } ( q _ { t } ) ) / \kappa ) } { \sum _ { q _ { t ^ { \prime } } \in \mathbb { Q } } \exp ( \mathcal { sim } ( p _ { c } ( c _ { t } ) , p _ { q } ( q _ { t ^ { \prime } } ) ) / \kappa ) } \right]\quad(2) Lm?=Etismasked?[?logqt?Q?exp(sim(pc?(ct?),pq?(qt?))/κ)exp(sim(pc?(ct?),pq?(qt?))/κ)?](2)
相似度函數定義為 sim(a,b)=a?b∥a∥∥b∥\text{sim}(a, b) = \frac{a^\top b}{\|a\|\|b\|}sim(a,b)=a∥∥ba?b?,其中 QQQ 是包含正樣本 qtq_tqt?KKK 個負樣本的集合,κ\kappaκ 是溫度參數。期望值僅在被掩蔽的位置上計算。多樣性損失 LdL_dLd? 防止量化模塊陷入退化映射(例如將所有輸入都映射到同一個離散碼),通過鼓勵量化概率 pg,vp_{g,v}pg,v? 在各個碼本條目間均勻分布來實現:
Ld=Et[1?1GV∑g=1Gexp?(?∑v=1Vpg,vlog?pg,v)](3)\mathcal { L } _ { d } = \mathbb { E } _ { t } \left[ 1 - \frac { 1 } { G V } \sum _ { g = 1 } ^ { G } \exp \left( - \sum _ { v = 1 } ^ { V } p _ { g , v } \log p _ { g , v } \right) \right]\quad(3) Ld?=Et?[1?GV1?g=1G?exp(?v=1V?pg,v?logpg,v?)](3)

溫馨提示:
閱讀全文請訪問"AI深語解構" SEW:無監督預訓練在語音識別中的性能-效率權衡

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

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

相關文章

linux系統部署express+vue項目

一、準備階段: 1、安裝linux上所需要的環境:npm nodejs nginx pm2 //安裝 npm(Node 包管理器) sudo apt install npm//判斷是否安裝成功 npm -v//安裝 Node.js(可以根據需要選擇版本) sudo apt inst…

PixiJS教程(004):點擊事件交互

1.6 事件交互實現要求:點擊寶劍,修改寶劍的顏色。1??實現代碼: // 為精靈添加交互事件 sprite.interactive true; sprite.on(click, () > {// 點擊精靈時,改變精靈的顏色sprite.tint Math.random() * 0xFFFFFF; });說明&am…

創客匠人助力家庭教育IP破局:從0到1打造創始人個人品牌全攻略

一、IP定位:細分賽道的精準錨定與用戶畫像構建 在家庭教育8000億市場規模的競爭中,創始人IP的差異化定位成為破局關鍵。創客匠人通過“標簽化定位”工具,幫助教育者鎖定垂直領域,如親子溝通、青春期教育等細分賽道。以景麗霞老師…

使用堅果云擴容Zotero同步空間的簡單快捷方法

本文介紹基于堅果云的WebDAV協議,用于文獻管理軟件Zotero的文件同步,從而實現Zotero存儲空間擴容的方法。 在之前的文章Zotero文獻管理軟件入門使用方法:軟件下載、文獻導入、引文插入(https://blog.csdn.net/zhebushibiaoshifu/a…

Java啟動腳本

Java啟動腳本 編寫代碼,然后打包 Java-1.0-SNAPSHOT.jar public class test {public static void main(String[] args) {System.out.println("Hello IDEA");} }編寫運行腳本 #!/bin/sh WORKDIR$(cd $(dirname $0); pwd) cd $WORKDIRexport JAVA_OPTS"…

VSCode使用ssh遠程連接阿里云

1. 終端選擇 Windows使用PowerShell Ubuntu和Mac使用Terminal 2. 設置ssh 2.1. 第一臺電腦 生成密鑰 ssh-keygen -o -t rsa -b 4096 -C "emailexample.com" 按三次回車 查看密鑰 cat ~/.ssh/id_rsa.pub 拷貝密鑰,粘貼到服務器的密鑰框中 2.2. 第…

XLSR-Wav2Vec2:用于語音識別的無監督跨語言表示學習

摘要 本文提出了 XLSR,該方法通過從多種語言的原始語音波形中預訓練單個模型,以學習跨語言的語音表示。我們基于 wav2vec 2.0 構建模型,該方法通過對掩蔽后的潛在語音表示解決對比任務進行訓練,并聯合學習在多種語言之間共享的潛…

圖靈完備之路(數電學習三分鐘)----數據選擇器與總線

1.數據選擇器之前我們學習了邏輯與算數的計算,得知兩個數字之間的加減和與或的結果是不同的,而一個通用的數字電路不可能只有一個功能,所以我們將在本節引入電路選擇器這一“器件”,來實現對兩個輸入的運算方式的選擇,…

Linux下如何設置CUDA的路徑

今天遇到一個關于CUDA的問題,我要跑的深度學習代碼,他里面有cuda編程,需要編譯。但是你運行就報錯。 代碼提示我大段報錯。 (score-denoise) ubuntuGPUA10002:~/wbd/score-denoise_Transformerdepth20$ python train.py Detected CUDA fil…

js樹的排序

樹 樹的前中后序遍歷 樹是一種重要的非線性數據結構,尤其是二叉樹。二叉樹的遍歷是操作樹的基礎,主要有前序遍歷、中序遍歷和后序遍歷三種方式。 前序遍歷 訪問順序:根結點 -> 左子樹 -> 右子樹。 遍歷規則:首先訪問根結…

解碼 Red Stuff:Walrus 高效可靠存儲的引擎

Red Stuff 是 Walrus 所采用的二維(2D)糾刪碼協議,定義了數據如何被編碼和存儲。它是實現高效、安全、且高可用的去中心化存儲的關鍵。通過 Red Stuff,Walrus 成功解決了去中心化存儲系統常見的三大難題:安全性、復制效…

【ACP】阿里云云計算高級運維工程師--ACP

文章目錄1、簡要介紹2、核心特點3、考試相關信息4、適合人群1、簡要介紹 阿里云云計算認證ACP(Alibaba Cloud Certified Professional)是面向云計算技術與應用從業者的專業級認證,旨在評估考生對阿里云云計算產品的理解、部署、運維及最佳實…

快速掌握Python編程基礎

干貨分享,感謝您的閱讀!備注:本博客將自己初步學習Python的總結進行分享,希望大家通過本博客可以在短時間內快速掌握Python的基本程序編碼能力,如有錯誤請留言指正,謝謝!(持續更新&a…

「Java案例」雞兔同籠問題

案例解析 雞兔同籠求解 《孫子算經》是中國古代重要的數學著作,成書于南北朝時期,其中就記載了一個有趣的問題:雞和兔在同一個籠子里,雞和兔共有n條腿, m個頭,問雞和兔各有多少只?編寫一個程序…

BLDC電機-運動控制---stm32時鐘樹定時器SYSTICKRTC的學習

一、時鐘樹 二、基本定時器 三、通用定時器 四、高級定時器 五、SYSTICK 六、RTC

Implementing a User-Defined Preconditioner in PETSc

文章目錄Implementing a User-Defined Preconditioner in PETScBasic ApproachExample ImplementationUsing Your PreconditionerAdvanced OptionsImportant NotesUsing PCShell to Implement User-Defined Preconditioners in PETScBasic Implementation StepsAdvanced Featur…

DotNetBrowser 3.3.0 版本發布啦!

#Chromium 137 安全修復一次調用即可下載 URL更新了 Widevine APIDOM 元素絕對邊界 🔗 點擊此處了解更多詳情。 🆓 獲取 30 天免費試用。

Android-自定義View的實戰學習總結

一、自定義View歌詞界面LrcView 類-->自定義的歌詞視圖1. 構造函數和屬性初始化自定義 View 通常需要提供多個構造函數以支持不同的初始化方式。在 LrcView 中,提供了四個構造函數,最終調用 super 父類構造函數完成初始化, context.obtain…

Maven 在 Eclipse 中的使用指南

Maven 在 Eclipse 中的使用指南 概述 Maven 是一個強大的構建自動化工具,用于項目管理和構建。它簡化了項目構建、依賴管理和項目報告等任務。Eclipse 是一個流行的集成開發環境(IDE),支持多種編程語言,包括 Java。本文將詳細介紹如何在 Eclipse 中使用 Maven 進行項目管…

zxing去白邊

2025年了,可能干不了幾年了,還能寫這種文章還是有點可笑。 背景 zxing庫生成的二維碼自帶白邊 分析 生產二維碼主要分兩步: 1.用QRCodeWriter生成BitMatrix信息 2.根據信息生成bitmap 問題在1。 生成二維碼的尺寸實際是有一些規格的&a…