日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

机器学习之手把手实现第1部分:支持向量机的原理和实现

發(fā)布時間:2025/4/5 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 机器学习之手把手实现第1部分:支持向量机的原理和实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

https://www.ibm.com/developerworks/cn/analytics/library/machine-learning-hands-on1-svn/index.html

本文將介紹機(jī)器學(xué)習(xí)領(lǐng)域經(jīng)典的支持向量機(jī) SVM 模型,它利用了軟間隔最大化、拉格朗日對偶、凸優(yōu)化、核函數(shù)、序列最小優(yōu)化等方法。支持向量機(jī)既可以解決線性可分的分類問題,也可完美解決線性不可分問題。您將看到 SVM 的原理介紹、SVM 實(shí)現(xiàn)步驟和詳解、SVM 實(shí)現(xiàn)代碼以及用 SVM 解決實(shí)際的分類問題。通過閱讀本文,您會對 SVM 的原理了如指掌,并可以自己開發(fā)出 SVM 的實(shí)現(xiàn)代碼。

關(guān)于機(jī)器學(xué)習(xí)的簡介

機(jī)器學(xué)習(xí)是從大量數(shù)據(jù)中學(xué)習(xí)出特定規(guī)律的算法。其中提到的規(guī)律有很多種,比如分類、聚類、回歸、關(guān)聯(lián)分析等。

分類就是給定大量帶標(biāo)簽的數(shù)據(jù),計(jì)算出未知標(biāo)簽樣本的標(biāo)簽取值。如年齡 40 歲以上、工科、研究生以上學(xué)歷,這類人薪資水平是高收入;年齡 20-30 歲、文科、大專學(xué)歷,這類人的薪資水平是低收入;現(xiàn)有一位 23 歲大專文科人士,求該人的薪資水平是哪類?根據(jù)分類建模,就可以知道這個人的薪資水平很可能是低收入。

聚類是將大量不帶標(biāo)簽的數(shù)據(jù)根據(jù)距離聚集成不同的簇,每一簇?cái)?shù)據(jù)有共同的特征。如電信行業(yè)可以根據(jù)用戶的月長途電話分鐘數(shù)、上網(wǎng)時長、短信使用數(shù)、地理位置、月消費(fèi)數(shù),將所有用戶聚集成有典型特征的簇,聚集出的某簇特征可能是月長途電話分鐘數(shù)長、上網(wǎng)時間長、地理位置變化不大、月消費(fèi)數(shù)目低,分析可得這類人極有可能是在校大學(xué)生,那么電信公司就可以針對這類特定人群制定有針對性的營銷策略。

回歸是根據(jù)特征值、目標(biāo)變量擬合出特征值與目標(biāo)變量之間的函數(shù)關(guān)系,可用來估計(jì)特征值對應(yīng)的目標(biāo)變量的可能取值。舉個簡單的例子,某市今年某 100 平米的房子價格是 80 萬,某 150 平米房子價格是 120 萬,那么某 200 平米的房子價格的取值就可能是 200*0.8=160 萬左右。

關(guān)聯(lián)分析是計(jì)算出大量數(shù)據(jù)之間的頻繁項(xiàng)集合。如超市訂單中有大量訂單同時包含啤酒與尿布,這其中的頻繁項(xiàng)就是啤酒和尿布,那么超市就可以針對這個規(guī)律對啤酒和尿布進(jìn)行組合促銷活動。

分類算法主要包括 K 近鄰、決策樹、樸素貝葉斯、邏輯回歸、支持向量機(jī)、AdaBoost 等;聚類主要包括線性回歸、嶺回歸、lasso、樹回歸等;聚類主要包括 K-Means 以及它的各種變形算法;關(guān)聯(lián)分析主要包括 Apriori、FP-growth 等算法。

支持向量機(jī)即 support vector machine(簡稱 SVM),是機(jī)器學(xué)習(xí)領(lǐng)域經(jīng)典的分類算法。

關(guān)于 SVM 的簡介

支持向量是距離分類超平面近的那些點(diǎn),SVM 的思想就是使得支持向量到分類超平面的間隔最大化。出發(fā)點(diǎn)很容易理解,距離分類超平面近的那些點(diǎn)到該超平面的間隔最大化代表了該超平面對兩類數(shù)據(jù)的區(qū)分度強(qiáng),不容易出現(xiàn)錯分的情況。如圖 1 所示,支持向量到超平面 1 的間隔大于支持向量到超平面 2 的間隔,因此超平面 1 優(yōu)于超平面 2。

圖 1. 兩個超平面示例

SVM 可以很好得解決二分類問題,對于多分類情況,就需要對模型進(jìn)行改動。如 one-versus-rest 法,這種方法每次選擇一個類別作為正樣本,剩下其他類別作為負(fù)樣本,假設(shè)一共有 3 個類別,這樣相當(dāng)于訓(xùn)練出了 3 個不同的 SVM。然后將測試數(shù)據(jù)分別帶入 3 個 SVM 模型中,得到的 3 個結(jié)果中的最大值則為最終的分類結(jié)果。

支持向量到分類超平面的間隔最大化的思路很完美,按這種思路得到的模型理論上是準(zhǔn)確度最高的一種模型。但是使用過 SVM 的朋友都知道,調(diào)用 SVM 算法的測試準(zhǔn)確度并不一定都很高。這其中有很多原因,比如數(shù)據(jù)預(yù)處理的效果、訓(xùn)練集的大小、特征值的選擇、參數(shù)設(shè)置以及核函數(shù)的選擇等因素。

任何模型都是優(yōu)點(diǎn)與缺點(diǎn)并存的。

SVM 的優(yōu)點(diǎn)是:

  • 可以解決線性不可分的情況。如圖 2 所示,兩類數(shù)據(jù)點(diǎn)根本無法用超平面分隔開;
  • 計(jì)算復(fù)雜度僅取決于少量支持向量,對于數(shù)據(jù)量大的數(shù)據(jù)集計(jì)算復(fù)雜度低。
  • SVM 的缺點(diǎn)是:

  • 經(jīng)典的 SVM 算法僅支持二分類,對于多分類問題需要改動模型;
  • 不支持類別型數(shù)據(jù),需在預(yù)處理階段將類別型數(shù)據(jù)轉(zhuǎn)換成離散型數(shù)據(jù)。類別型數(shù)據(jù)即"男"、 "女"這類由字符串表示某類信息的數(shù)據(jù),需將這類數(shù)據(jù)轉(zhuǎn)換成離散型數(shù)據(jù)如 1、2。
  • 圖 2. 線性不可分問題

    SVM 基本原理

    SVM 原理分為軟間隔最大化、拉格朗日對偶、最優(yōu)化問題求解、核函數(shù)、序列最小優(yōu)化?SMO?等部分。雖然這些名詞看起來很晦澀,但是深入探索后就會發(fā)現(xiàn)其中的思想并沒有那么復(fù)雜。

    軟間隔最大化

    SVM 的核心思路是最大化支持向量到分隔超平面的間隔。后面所有的推導(dǎo)都是以最大化此間隔為核心思想展開。一般的機(jī)器學(xué)習(xí)問題都是先得到模型的目標(biāo)函數(shù)和約束條件,然后在約束條件下對目標(biāo)函數(shù)求得最優(yōu)解。因此,我們下面首先需要推導(dǎo)出 SVM 模型的目標(biāo)函數(shù)和約束條件。

    既然要最大化間隔,那么回顧下點(diǎn) x 到超平面(w,b)的距離公式:

    其中超平面的公式為:

    由此可推出點(diǎn) x 到超平面(w,b)的幾何間隔為:

    其中 xi 代表第 i 條數(shù)據(jù),yi 代表第 i 條數(shù)據(jù)對應(yīng)的目標(biāo)變量的取值,取值有+1 和-1 兩種。所以當(dāng)?shù)?i 條數(shù)據(jù)被正確分類時,y 取值和 w*x+b 取值的正負(fù)一致,幾何間隔為正;當(dāng)被錯誤分類時,y 取值和 w*x+b 取值的正負(fù)相反,幾何間隔為負(fù)。

    圖 3. 樣本數(shù)據(jù)關(guān)于 w*x+b 的取值符號

    定義幾何間隔中最小的為:

    由此,可以得到間隔最大化問題的目標(biāo)函數(shù):

    并遵循如下約束條件:

    做如下變換:

    則目標(biāo)函數(shù)轉(zhuǎn)換為:

    相應(yīng)的約束條件變?yōu)?#xff1a;

    做如下變換:

    可得目標(biāo)函數(shù)和約束條件變?yōu)?#xff1a;

    由于 w, b 成倍數(shù)變化并不會影響超平面的公式,所以:

    此時得到最終的間隔最大化的目標(biāo)函數(shù)和約束條件如下:

    但是,到這里并沒有真正得結(jié)束。考慮到現(xiàn)實(shí)生活中的真實(shí)數(shù)據(jù),存在一些特異點(diǎn)即 outliers,這些數(shù)據(jù)點(diǎn)并不滿足上面推導(dǎo)出的約束條件,如圖 4 所示,圖中點(diǎn) A 就是 outlier 特異點(diǎn)。

    圖 4. Outlier 特異點(diǎn)

    為了解決這種問題,對每個樣本點(diǎn)引進(jìn)一個松弛變量,使得約束條件變?yōu)?#xff1a;

    這樣給 outlier 的約束條件加上一個變量,使其可以滿足大于等于 1 的條件。則相應(yīng)的目標(biāo)變量變?yōu)?#xff1a;

    其中 C 為懲罰參數(shù),它的目的是使得目標(biāo)變量最小即幾何間隔最大,且使得松弛變量最小化。加入松弛變量的目標(biāo)函數(shù)就是軟間隔最大化。

    拉格朗日對偶

    對于凸二次優(yōu)化問題,通過引入拉格朗日乘子,將目標(biāo)函數(shù)和約束條件整合到拉格朗日函數(shù)中,這樣能方便求解最值問題。那么,對每個不等式約束引入拉格朗日乘子,得到拉格朗日函數(shù)如下:

    分析可知:

    則原最優(yōu)化問題轉(zhuǎn)換成:

    由于原最優(yōu)化問題直接求解很困難,利用拉格朗日對偶性,可通過求解原最優(yōu)化問題的對偶問題得到原問題的最優(yōu)解。原最優(yōu)化問題的對偶問題為:

    最優(yōu)化問題求解

    到此為止,已經(jīng)將目標(biāo)函數(shù)和約束條件轉(zhuǎn)換成了極大極小化拉格朗日函數(shù)的問題了。首先求解關(guān)于拉格朗日函數(shù)的極小化問題。

    對三個變量分別求偏導(dǎo)得:

    將以上三式帶入拉格朗日函數(shù)中得:

    那么極大極小化拉格朗日函數(shù)轉(zhuǎn)換成:

    為求解方便,將極大轉(zhuǎn)換成極小得:

    核函數(shù)

    對于線性不可分問題,如圖 2 所示,這類問題是無法用超平面劃分正負(fù)樣本數(shù)據(jù)的。倘若能將超平面換成超曲面,則可以將正負(fù)樣本正確分類,如圖 5 所示。

    圖 5. 超曲面分離正負(fù)樣本

    我們知道曲面的公式是:

    映射到新坐標(biāo)如下:

    可將超曲面在新坐標(biāo)下表示成超平面:

    也就是將在二維空間(x1,x2)下線性不可分的問題轉(zhuǎn)換成了在五維空間(z1,z2,z3,z4,z5)下線性可分的問題。

    得映射后新坐標(biāo)下的內(nèi)積:

    有一核函數(shù)如下:

    可知

    何為核函數(shù)?核函數(shù)在低維空間中完成了映射到高維空間后的內(nèi)積運(yùn)算。這點(diǎn)非常有用,利用核函數(shù),無需先將變量一一映射到高維空間再計(jì)算內(nèi)積,而是簡單得在低維空間中利用核函數(shù)完成這一操作。為什么說不用一一映射到高維空間很有用呢?原因就在于首先我們無法針對每種情況提供精確的映射函數(shù),再者對于需要映射到無窮維的情況顯然無法一一映射完成。

    那么為什么是映射到高維后的內(nèi)積運(yùn)算呢?這是因?yàn)樵谏瞎?jié)中我們得到了如下目標(biāo)函數(shù):

    正是因?yàn)樵撃繕?biāo)函數(shù)中包含自變量的內(nèi)積運(yùn)算,而映射到高維空間后的內(nèi)積運(yùn)算又恰好可以通過核函數(shù)在低維空間中直接求得,故而有了核函數(shù)的由來。較常用的核函數(shù)是高斯核,高斯核可以將低維空間映射到無窮維。

    運(yùn)用核函數(shù)后,最優(yōu)化問題的目標(biāo)函數(shù)和約束條件變?yōu)?#xff1a;

    序列最小優(yōu)化 (Sequential minimal optimization)

    到目前為止,優(yōu)化問題已經(jīng)轉(zhuǎn)化成了一個包含 N 個 alpha 自變量的目標(biāo)變量和兩個約束條件。由于目標(biāo)變量中自變量 alpha 有 N 個,為了便與求解,每次選出一對自變量 alpha,然后求目標(biāo)函數(shù)關(guān)于其中一個 alpha 的偏導(dǎo),這樣就可以得到這一對 alpha 的新值。給這一對 alpha 賦上新值,然后不斷重復(fù)選出下一對 alpha 并執(zhí)行上述操作,直到達(dá)到最大迭代數(shù)或沒有任何自變量 alpha 再發(fā)生變化為止,這就是 SMO 的基本思想。說直白些,SMO 就是在約束條件下對目標(biāo)函數(shù)的優(yōu)化求解算法。

    為何不能每次只選一個自變量進(jìn)行優(yōu)化?那是因?yàn)橹贿x一個自變量 alpha 的話,會違反第一個約束條件,即所有 alpha 和 y 值乘積的和等于 0。

    下面是詳細(xì)的 SMO 過程。假設(shè)選出了兩個自變量分別是 alpha1 和 alpha2,除了這兩個自變量之外的其他自變量保持固定,則目標(biāo)變量和約束條件轉(zhuǎn)化為:

    將約束條件中的 alpha1 用 alpha2 表示,并代入目標(biāo)函數(shù)中,則將目標(biāo)函數(shù)轉(zhuǎn)化成只包含 alpha2 的目標(biāo)函數(shù),讓該目標(biāo)函數(shù)對 alpha2 的偏導(dǎo)等于 0:

    可求得 alpha2 未經(jīng)修剪的值:

    之所以說 alpha2 是未經(jīng)修剪的值是因?yàn)樗?alpha 都必須滿足大于等于 0 且小于等于 C 的約束條件,用此約束條件將 alpha2 進(jìn)行修剪,修剪過程如下:

    由此得:

    分兩種情況討論:

    情況 1.當(dāng) y1 等于 y2 時,有:

    情況 2.當(dāng) y1 不等于 y2 時,有:

    修剪后,可得 alpha2 的取值如下:

    由 alpha2 和 alpha1 的關(guān)系,可得:

    在完成 alpha1 和 alpha2 的一輪更新后,需要同時更新 b 的值,當(dāng) alpha1 更新后的值滿足 0<alpha1<C 時,由 KKT 條件得:

    由于篇幅有限,在此就不把推導(dǎo)過程一一列舉,可得:

    同樣的道理,當(dāng) alpha2 更新后的值滿足 0<alpha1<C 時可得:

    若更新后的 alpha1 和 alpha2 同時滿足大于 0 且小于 C 的條件,那么 b 就等于 b1 等于 b2;否則,b 取 b1 和 b2 的中點(diǎn)。

    那么問題來了,如何選擇 alpha1 和 alpha2 呢?

    選擇違背下列 KKT 條件推導(dǎo)結(jié)果的 alpha 作為 alpha1:

    為了讓每次變化盡可能大,alpha2 的選擇滿足如下式子最大,即步長最大化:

    其中 E 是上面提到過的預(yù)測值和真實(shí)值差值的絕對值,也就是誤差值。

    按上述方法不斷選擇一對 alpha 并更新,直到達(dá)到最大迭代次數(shù)或所有 alpha 都不再變化,則停止迭代。有朋友就會問,求出 alpha 之后呢?如何判斷新樣本數(shù)據(jù)屬于 1 還是-1 呢?

    別忘了,在最優(yōu)化求解一節(jié),我們得到了如下:

    若 f(x)大于 0,則新樣本數(shù)據(jù)屬于 1;否則,新樣本數(shù)據(jù)屬于-1。

    可以見得,求出 alpha 后,所有問題都迎刃而解了。

    實(shí)現(xiàn)步驟: 自己動手實(shí)現(xiàn) SVM

    以上都為推導(dǎo)部分,實(shí)現(xiàn)代碼主要圍繞對目標(biāo)函數(shù)的優(yōu)化求解上,即序列最小優(yōu)化算法部分。

    清單 1. alpha1 選擇

    1 2 3 4 5 6 yI = diyObj.yMat[alphaI] EI = calcE(alphaI, diyObj) diyObj.E[alphaI] = [1, EI] # if alpha1 violates KKT if((yI * EI > diyObj.toler and diyObj.alphas[alphaI] > 0) or (yI * EI < - diyObj.toler and diyObj.alphas[alphaI] < diyObj.C)):

    選擇違背 KKT 條件推導(dǎo)結(jié)果的 alpha 作為 alpha1,本代碼中 diyObj.toler 取值為 0.0001。

    清單 2. alpha2 選擇

    1 2 3 4 5 6 7 8 for j in nonzeroEIndex: if alphaI == j: continue EJtemp = calcE(j, diyObj) deltaE = abs(EI - EJtemp) if(deltaE > maxDelta): maxDelta = deltaE alphaJ = j EJ = EJtemp

    alpha2 的選擇遵循步長最大化,即 E 值與 alpha1 的 E 值相差最大的 alpha 選為 alpha2。

    清單 3. alpha1,alpha2,b 求解

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 alpha1old = diyObj.alphas[alphaI].copy() alpha2old = diyObj.alphas[alphaJ].copy() eta = diyObj.K[alphaI,alphaI] + diyObj.K[alphaJ, alphaJ] - 2 * diyObj.K[alphaI, alphaJ] if eta <= 0: return 0 alpha2newUnclip = alpha2old + yJ * (EI - EJ) / eta if(yI == yJ): L = max(0, alpha1old + alpha2old - diyObj.C) H = min(diyObj.C, alpha1old + alpha2old) else: L = max(0, alpha2old - alpha1old) H = min(diyObj.C, diyObj.C - alpha1old + alpha2old) if L == H: return 0 alpha2new = clipAlpha(alpha2newUnclip, L, H) if abs(alpha2new - alpha2old) < 0.00001: return 0 alpha1new = alpha1old + yI * yJ * (alpha2old - alpha2new) b1new = - EI - yI * diyObj.K[alphaI,alphaI] * (alpha1new - alpha1old) \ - yJ * diyObj.K[alphaJ, alphaI] * (alpha2new - alpha2old) + diyObj.b b2new = - EJ - yI * diyObj.K[alphaI,alphaJ] * (alpha1new - alpha1old) \ - yJ * diyObj.K[alphaJ, alphaJ] * (alpha2new - alpha2old) + diyObj.b b = calcb(b1new, b2new)

    先算出 alpha 取值的上下界,求出 alpha2 后用上下界進(jìn)行裁剪。用裁剪后的 alpha2 新值計(jì)算 alpha1 新值。b 的取值由 b1 和 b2 綜合決定。

    清單 4. 核函數(shù)

    1 2 3 4 5 6 7 8 9 10 def transfer2Kernel(X, Xi, kernelParam): m = shape(X)[0] Ktemp = mat(zeros((m, 1))) if kernelParam[0]=="rbf": for i in range(m): xdelta = X[i,:] - Xi Ktemp[i] = xdelta * xdelta.T Ktemp = exp(-Ktemp/kernelParam[1]**2) else: raise NameError("undefined kernel name!") return Ktemp

    本代碼中使用高斯核完成從低維到高維的映射。

    代碼下載 (code downloads)

    本文所有 SVM 實(shí)現(xiàn)代碼可在文末下載。

    本文數(shù)據(jù)集簡介

    圖 6. 數(shù)據(jù)集樣例

    數(shù)據(jù)集是獻(xiàn)血中心關(guān)于某人是否在 2007 年三月獻(xiàn)血的數(shù)據(jù)。前四列分別代表距離上次獻(xiàn)血的月份數(shù)、總獻(xiàn)血次數(shù)、總獻(xiàn)血毫升數(shù)、距離第一次獻(xiàn)血的月份數(shù)。最后一列代表是否在 2007 年三月獻(xiàn)血,1 代表是,-1 代表否。本數(shù)據(jù)集共 748 條。

    應(yīng)用示例: 應(yīng)用實(shí)現(xiàn)的 SVM 解決實(shí)際問題

    清單 5. 用 SVM 解決實(shí)際問題

    1 2 3 4 5 6 7 8 9 10 11 dataMat,yMat = loadDataset("bloodTransfusion.txt") alphas,b = smo(dataMat, yMat, 200, 0.0001,100, ("rbf",20)) #yi of testData: 1,1,1,-1,-1,-1,-1,1,1,-1 testData = [[2,50,12500,98],[0,13,3250,28],[1,16,4000,35],[1,24,6000,77],[4,4,1000,4] ?,[1,12,3000,35],[4,23,5750,58],[2,7,1750,14],[2,10,2500,28],[1,13,3250,47]] m, n = shape(testData) testmat = mat(testData) for i in range(m): kernelEval = transfer2Kernel(mat(dataMat), testmat[i,:],("rbf",20)) predict = kernelEval.T * multiply(mat(yMat).transpose(), alphas) + b print(sign(predict))

    用 bloodTransfusion 數(shù)據(jù)集訓(xùn)練 SVM 模型,得到該模型的 alpha 矩陣和 b 值。然后將 10 條測試數(shù)據(jù)輸入模型中,輸出結(jié)果為 10 條測試數(shù)據(jù)對應(yīng)的預(yù)測值。

    表 1. 應(yīng)用本文實(shí)現(xiàn)的 SVM 對 10 條數(shù)據(jù)進(jìn)行預(yù)測的結(jié)果示例
    特征值預(yù)測值真實(shí)值

    從表中可以看出,8 條數(shù)據(jù)分類正確,2 條數(shù)據(jù)分類有誤。要想提高模型準(zhǔn)確度,可以修改模型參數(shù)如最大迭代數(shù)、C 懲罰系數(shù)、高斯核參數(shù)等。

    總結(jié)

    本文首先介紹了機(jī)器學(xué)習(xí)的體系框架,接著詳細(xì)深入地講解了 SVM 的基本原理,分別為軟間隔最大化、拉格朗日對偶、最優(yōu)化問題求解、核函數(shù)和序列最小優(yōu)化等。通過代碼樣例,介紹了在自己動手實(shí)現(xiàn) SVM 模型時的思路。最后,用獻(xiàn)血中心的數(shù)據(jù)展示了如何應(yīng)用 SVM 解決實(shí)際問題。本文的內(nèi)容不算高深,讀者如果能靜下心來細(xì)讀,將會有很大收獲。如若文中有紕漏的地方,歡迎廣大讀者留言指正,也很期待在接下來的機(jī)器學(xué)習(xí)系列文章中繼續(xù)和志同道合的讀者相遇。

    參考資源

    本文用到的參考文獻(xiàn)如下:

    • 參考李航著《統(tǒng)計(jì)學(xué)習(xí)方法》,了解 SVM 基本原理。
    • 參考 Peter Harrington 著《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》,了解 SVM 代碼框架。
    • 參考周志華著《機(jī)器學(xué)習(xí)》,了解 SVM 基本思路。
    • http://archive.ics.uci.edu/ml/datasets/Blood+Transfusion+Service+Center,本文所用數(shù)據(jù)集網(wǎng)址。

    轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/articles/8926969.html

    總結(jié)

    以上是生活随笔為你收集整理的机器学习之手把手实现第1部分:支持向量机的原理和实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。