Python-鳶尾花數據集/月亮數據集的線性LDA、k-means和SVM算法二分類可視化分析

本博客是Jupyter Notebook的python3環境下運行的。
具體內容是對鳶尾花數據集和月亮數據集,分別採用線性LDA、k-means和SVM算法進行二分類可視化分析。簡述SVM算法的優點。

線性判別分析LDA

LDA是一種有監督的數據降維方法。LDA在進行數據降維的時候是利用數據的類別標籤提供的信息的。
將帶有標籤的數據降維,投影到低維空間同時滿足三個條件:
1、儘可能多地保留數據樣本的信息(即選擇最大的特徵是對應的特徵向量所代表的的方向)。
2、尋找使樣本儘可能好分的最佳投影方向。
3、投影后使得同類樣本儘可能近,不同類樣本儘可能遠。

鳶尾花數據集

代碼如下:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_classification

class LDA():
    def Train(self, X, y):
        # X爲訓練數據集,y爲訓練label
        X1 = np.array([X[i] for i in range(len(X)) if y[i] == 0])
        X2 = np.array([X[i] for i in range(len(X)) if y[i] == 1])
        # 求中心點
        mju1 = np.mean(X1, axis=0)  # mju1是ndrray類型
        mju2 = np.mean(X2, axis=0)
        # dot(a, b, out=None) 計算矩陣乘法
        cov1 = np.dot((X1 - mju1).T, (X1 - mju1))
        cov2 = np.dot((X2 - mju2).T, (X2 - mju2))
        Sw = cov1 + cov2
        # 計算w
        w = np.dot(np.mat(Sw).I, (mju1 - mju2).reshape((len(mju1), 1)))
        # 記錄訓練結果
        self.mju1 = mju1  # 第1類的分類中心
        self.cov1 = cov1
        self.mju2 = mju2  # 第2類的分類中心
        self.cov2 = cov2
        self.Sw = Sw  # 類內散度矩陣
        self.w = w  # 判別權重矩陣
    def Test(self, X, y):
        """X爲測試數據集,y爲測試label"""
        # 分類結果
        y_new = np.dot((X), self.w)
        # 計算fisher線性判別式
        nums = len(y)
        c1 = np.dot((self.mju1 - self.mju2).reshape(1, (len(self.mju1))), np.mat(self.Sw).I)
        c2 = np.dot(c1, (self.mju1 + self.mju2).reshape((len(self.mju1), 1)))
        c = 1/2 * c2  # 2個分類的中心
        h = y_new - c
        # 判別
        y_hat = []
        for i in range(nums):
            if h[i] >= 0:
                y_hat.append(0)
            else:
                y_hat.append(1)
        # 計算分類精度
        count = 0
        for i in range(nums):
            if y_hat[i] == y[i]:
                count += 1
        precise = count / nums
        # 顯示信息
        print("測試樣本數量:", nums)
        print("預測正確樣本的數量:", count)
        print("測試準確度:", precise)
        return precise
    
if '__main__' == __name__:
    # 產生分類數據
    n_samples = 500
    X, y = make_classification(n_samples=n_samples, n_features=2, n_redundant=0, n_classes=2,n_informative=1, n_clusters_per_class=1, class_sep=0.5, random_state=10)
    # LDA線性判別分析(二分類)
    lda = LDA()
    # 60% 用作訓練,40%用作測試
    Xtrain = X[:299, :]
    Ytrain = y[:299]
    Xtest = X[300:, :]
    Ytest = y[300:]
    lda.Train(Xtrain, Ytrain)
    precise = lda.Test(Xtest, Ytest)
    # 原始數據
    plt.scatter(X[:, 0], X[:, 1], marker='o', c=y)
    plt.xlabel("x1")
    plt.ylabel("x2")
    plt.title("Test precise:" + str(precise))
    plt.show()

運行結果如下所示:
在這裏插入圖片描述

月亮數據集

代碼如下:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
class LDA():
    def Train(self, X, y):
        # X爲訓練數據集,y爲訓練label
        X1 = np.array([X[i] for i in range(len(X)) if y[i] == 0])
        X2 = np.array([X[i] for i in range(len(X)) if y[i] == 1])
        # 求中心點
        mju1 = np.mean(X1, axis=0)  # mju1是ndrray類型
        mju2 = np.mean(X2, axis=0)
        # dot(a, b, out=None) 計算矩陣乘法
        cov1 = np.dot((X1 - mju1).T, (X1 - mju1))
        cov2 = np.dot((X2 - mju2).T, (X2 - mju2))
        Sw = cov1 + cov2
        # 計算w
        w = np.dot(np.mat(Sw).I, (mju1 - mju2).reshape((len(mju1), 1)))
        # 記錄訓練結果
        self.mju1 = mju1  # 第1類的分類中心
        self.cov1 = cov1
        self.mju2 = mju2  # 第1類的分類中心
        self.cov2 = cov2
        self.Sw = Sw  # 類內散度矩陣
        self.w = w  # 判別權重矩陣
    def Test(self, X, y): #X爲測試數據集,y爲測試label
        # 分類結果
        y_new = np.dot((X), self.w)
        # 計算fisher線性判別式
        nums = len(y)
        c1 = np.dot((self.mju1 - self.mju2).reshape(1, (len(self.mju1))), np.mat(self.Sw).I)
        c2 = np.dot(c1, (self.mju1 + self.mju2).reshape((len(self.mju1), 1)))
        c = 1/2 * c2  # 2個分類的中心
        h = y_new - c
        # 判別
        y_hat = []
        for i in range(nums):
            if h[i] >= 0:
                y_hat.append(0)
            else:
                y_hat.append(1)
        # 計算分類精度
        count = 0
        for i in range(nums):
            if y_hat[i] == y[i]:
                count += 1
        precise = count / (nums+0.000001)
        # 顯示信息
        print("測試樣本數量:", nums)
        print("預測正確樣本的數量:", count)
        print("測試準確度:", precise)
        return precise
if '__main__' == __name__:
    # 產生分類數據
    X, y = make_moons(n_samples=100, noise=0.15, random_state=42)
    # LDA線性判別分析(二分類)
    lda = LDA()
    # 60% 用作訓練,40%用作測試
    Xtrain = X[:60, :]
    Ytrain = y[:60]
    Xtest = X[40:, :]
    Ytest = y[40:]
    lda.Train(Xtrain, Ytrain)
    precise = lda.Test(Xtest, Ytest)
    # 原始數據
    plt.scatter(X[:, 0], X[:, 1], marker='o', c=y)
    plt.xlabel("x1")
    plt.ylabel("x2")
    plt.title("Test precise:" + str(precise))
    plt.show()

運行結果如下:
在這裏插入圖片描述

SVM(支持向量機)算法

支持向量機(support vector machine)是一種分類算法,通過尋求結構化風險最小來提高學習機泛化能力,實現經驗風險和置信範圍的最小化,從而達到在統計樣本量較少的情況下,亦能獲得良好統計規律的目的。通俗來講,它是一種二類分類模型,其基本模型定義爲特徵空間上的間隔最大的線性分類器,即支持向量機的學習策略便是間隔最大化,最終可轉化爲一個凸二次規劃問題的求解。

支持向量機(SVM)的優點

SVM學習問題可以表示爲凸優化問題,可利用已知的有效算法發現目標函數的全局最小值。而其他分類方法(如基於規則的分類器和人工神經網絡)都採用一種基於貪心學習的策略來搜索假設空間,這種方法一般只能獲得局部最優解。
SVM是基於小樣本統計理論的基礎上的,這符合機器學習的目的。而且支持向量機比神經網絡具有較好的泛化推廣能力。
SVM使用非線性分類器具有較大的優勢,而邏輯模式以及決策樹模式都是使用了直線方法。
SVM理論提供了一種避開高維空間的複雜性,直接用此空間的內積函數(即核函數),再利用在線性可分的情況下的求解方法直接求解對應的高維空間的決策問題。當核函數已知,可以簡化高維空間問題的求解難度。

鳶尾花數據集

代碼如下:

from sklearn.svm import SVC
from sklearn import datasets
import matplotlib.pyplot as plt
import numpy as np
iris = datasets.load_iris()
X = iris["data"][:, (2, 3)]  # 花瓣長度與花瓣寬度  petal length, petal width
y = iris["target"]
setosa_or_versicolor = (y == 0) | (y == 1)
X = X[setosa_or_versicolor]
y = y[setosa_or_versicolor]
# SVM Classifier model
svm_clf = SVC(kernel="linear", C=float("inf"))
svm_clf.fit(X, y)
def plot_svc_decision_boundary(svm_clf, xmin, xmax):
    # 獲取決策邊界的w和b
    w = svm_clf.coef_[0]
    b = svm_clf.intercept_[0]

    # At the decision boundary, w0*x0 + w1*x1 + b = 0
    # => x1 = -w0/w1 * x0 - b/w1
    x0 = np.linspace(xmin, xmax, 200)
    # 畫中間的粗線
    decision_boundary = -w[0]/w[1] * x0 - b/w[1]
    # 計算間隔
    margin = 1/w[1]
    gutter_up = decision_boundary + margin
    gutter_down = decision_boundary - margin
    # 獲取支持向量
    svs = svm_clf.support_vectors_
    plt.scatter(svs[:, 0], svs[:, 1], s=180, facecolors='#FFAAAA')
    plt.plot(x0, decision_boundary, "k-", linewidth=2)
    plt.plot(x0, gutter_up, "k--", linewidth=2)
    plt.plot(x0, gutter_down, "k--", linewidth=2)
plt.title("大間隔分類", fontsize=16)
plt.rcParams['font.sans-serif']=['SimHei'] #顯示中文標籤
plt.rcParams['axes.unicode_minus']=False
plot_svc_decision_boundary(svm_clf, 0, 5.5)
plt.plot(X[:, 0][y==1], X[:, 1][y==1], "bs")
plt.plot(X[:, 0][y==0], X[:, 1][y==0], "yo")
plt.xlabel("Petal length", fontsize=14)
plt.axis([0, 5.5, 0, 2])
plt.show()

運行結果如下:
實線代表SVM分類器的決策邊界,這條線不僅分離了兩個類別,並且儘可能遠離了最近的訓練實例。我們可以將SVM分類器視爲在類別之間擬合可能的最寬的街道,平行的虛線所示。

在這裏插入圖片描述

月亮數據集

代碼如下:

import matplotlib.pyplot as plt
from sklearn.pipeline import Pipeline
import numpy as np
import matplotlib as mpl
from sklearn.datasets import make_moons
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC
# 爲了顯示中文
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
X, y = make_moons(n_samples=100, noise=0.15, random_state=42)
def plot_dataset(X, y, axes):
    plt.plot(X[:, 0][y==0], X[:, 1][y==0], "bs")
    plt.plot(X[:, 0][y==1], X[:, 1][y==1], "g^")
    plt.axis(axes)
    plt.grid(True, which='both')
    plt.xlabel(r"$x_1$", fontsize=20)
    plt.ylabel(r"$x_2$", fontsize=20, rotation=0)
    plt.title("月亮數據",fontsize=20)
plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
plt.show()

運行結果如下:
在這裏插入圖片描述
代碼如下:

from sklearn.datasets import make_moons
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures

polynomial_svm_clf = Pipeline([
        # 將源數據 映射到 3階多項式
        ("poly_features", PolynomialFeatures(degree=3)),
        # 標準化
        ("scaler", StandardScaler()),
        # SVC線性分類器
        ("svm_clf", LinearSVC(C=10, loss="hinge", random_state=42))
    ])

polynomial_svm_clf.fit(X, y)

運行結果如下:
Pipeline(memory=None,
steps=[(‘poly_features’,
PolynomialFeatures(degree=3, include_bias=True,
interaction_only=False, order=‘C’)),
(‘scaler’,
StandardScaler(copy=True, with_mean=True, with_std=True)),
(‘svm_clf’,
LinearSVC(C=10, class_weight=None, dual=True,
fit_intercept=True, intercept_scaling=1,
loss=‘hinge’, max_iter=1000, multi_class=‘ovr’,
penalty=‘l2’, random_state=42, tol=0.0001,
verbose=0))],
verbose=False)

代碼如下:

def plot_predictions(clf, axes):
    # 打表
    x0s = np.linspace(axes[0], axes[1], 100)
    x1s = np.linspace(axes[2], axes[3], 100)
    x0, x1 = np.meshgrid(x0s, x1s)
    X = np.c_[x0.ravel(), x1.ravel()]
    y_pred = clf.predict(X).reshape(x0.shape)
    y_decision = clf.decision_function(X).reshape(x0.shape)
#     print(y_pred)
#     print(y_decision)
    
    plt.contourf(x0, x1, y_pred, cmap=plt.cm.brg, alpha=0.2)
    plt.contourf(x0, x1, y_decision, cmap=plt.cm.brg, alpha=0.1)

plot_predictions(polynomial_svm_clf, [-1.5, 2.5, -1, 1.5])
plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])

plt.show()

運行結果如下:
在這裏插入圖片描述

代碼如下:

from sklearn.svm import SVC
gamma1, gamma2 = 0.1, 5
C1, C2 = 0.001, 1000
hyperparams = (gamma1, C1), (gamma1, C2)
svm_clfs = []
for gamma, C in hyperparams:
    rbf_kernel_svm_clf = Pipeline([
            ("scaler", StandardScaler()),
            ("svm_clf", SVC(kernel="rbf", gamma=gamma, C=C))
        ])
    rbf_kernel_svm_clf.fit(X, y)
    svm_clfs.append(rbf_kernel_svm_clf)
plt.figure(figsize=(11, 7))
for i, svm_clf in enumerate(svm_clfs):
    plt.subplot(221 + i)
    plot_predictions(svm_clf, [-1.5, 2.5, -1, 1.5])
    plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
    gamma, C = hyperparams[i]
    plt.title(r"$\gamma = {}, C = {}$".format(gamma, C), fontsize=16)
plt.tight_layout()
plt.show()

運行結果如下:
在這裏插入圖片描述

k-means聚類分析

聚類算法是指將一堆沒有標籤的數據自動劃分成幾類的方法,屬於無監督學習方法,這個方法要保證同一類的數據有相似的特徵。
根據樣本之間的距離或者說是相似性(親疏性),把越相似、差異越小的樣本聚成一類(簇),最後形成多個簇,使同一個簇內部的樣本相似度高,不同簇之間差異性高。

鳶尾花數據集

代碼如下:

from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
#加載數據集
lris_df = datasets.load_iris()
#print(lris_df) 
#挑選第2列,花瓣的長度
x_axis = lris_df.data[:,2]
#print(x_axis)
#挑選第三列,花瓣的寬度
y_axis = lris_df.data[:,3]
#print(y_axis)
#這裏已經知道了分2類,其他分類這裏的參數需要調試
model = KMeans(n_clusters=2)
#訓練模型
model.fit(lris_df.data)
prddicted_label= model.predict([[6.3, 3.3, 6, 2.5]])
all_predictions = model.predict(lris_df.data)
#plt.plot(a, b, "bs")
plt.xlabel('花瓣的長度')
plt.ylabel('花瓣的寬度')
plt.rcParams['font.sans-serif']=['SimHei'] #顯示中文標籤
plt.rcParams['axes.unicode_minus']=False
#打印出來對150條數據的聚類散點圖
plt.scatter(x_axis, y_axis, c=all_predictions)
plt.show()

運行結果如下:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-sANQyhx2-1589852066780)(output_16_0.png)]

月亮數據集

代碼如下:

from sklearn.datasets import make_moons
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
import numpy as np
X, y = make_moons(n_samples=100, noise=0.15, random_state=42)
#X是一個100X2維度的,分別選取兩列的數據
X1=X[:,0]
X2=X[:,1]
#這裏已經知道了分2類,其他分類這裏的參數需要調試
model = KMeans(n_clusters=2)
#訓練模型
model.fit(X)
#print(z[50])
#選取行標爲50的那條數據,進行預測
prddicted_label= model.predict([[-0.22452786,1.01733299]])
#預測全部100條數據
all_predictions = model.predict(X)
#plt.plot(a, b, "bs")
#打印聚類散點圖
plt.scatter(X1, X2, c=all_predictions)
plt.show()

運行結果如下:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章