• 降维:LDA推导及iris实例


    线性判别分析

    \qquad 线性判别分析在降维中的运用:用过将高维的样本投影到最佳的矢量空间,投影后的样本在新的子空间有最大类间距离以及最小类内距离。也就是使投影后的数据内间散度矩阵大,类内散度矩阵小,等价于相同类别数据紧凑,不用类别离得远。

    PCA与LDA之间的区别?

    PCALDA
    无监督的数据降维方法有监督的数据降维方法
    不使用数据标签使用用数据标签
    投影到方差最大的相互正交的方向上(保留更多的信息)尽可能多的保留样本信息;寻找使样本尽可能好分的方向;同类近,不同尽可能远
    最多降到类别数N-1维
    可用于分类

    LDA推导

    二分类

    在这里插入图片描述
    数据集:D={( x 1 x_1 x1, y 1 y_1 y1),( x 2 x_2 x2, y 2 y_2 y2)…( x m x_m xm, y m y_m ym)} \qquad y i y_i yi∈{0,1} \qquad x i x_i xi R n × 1 R^{n×1} Rn×1
    n:特征数
    m:样本数量
    m i m_i mi:第i类样本数量
    待求:投影方向 w w w \qquad w w w R n × 1 R^{n×1} Rn×1
    μ i μ_i μi:第i类数据集的样本均值
    ∑ i \sum_i i:第类数据集变换前的散度矩阵
    \qquad \qquad ∑ i \sum_i i= ∑ x ∈ X i \sum_{x∈X_i} xXi( x x x- μ i μ_i μi)( x x x- μ i μ_i μi ) T )^T )T
     
    X i X_i Xi:第i类拥有的数据集
    w T w^T wT μ i μ_i μi:第i类中心在 w w w上的投影 \qquad w T w^T wT μ i μ_i μi R 1 × 1 R^{1×1} R1×1
    w T w^T wT x i x_i xi:第i个样本在 w w w上的投影 \qquad w T w^T wT x i x_i xi R 1 × 1 R^{1×1} R1×1
    w T w^T wT ∑ i \sum_i i w w w:投影后的方差 \qquad w T w^T wT ∑ i \sum_i i w w w R 1 × 1 R^{1×1} R1×1
    \qquad \qquad ∑ x ∈ X i \sum_{x∈X_i} xXi( w T w^T wT x x x- w T w^T wT μ i μ_i μi)( w T w^T wT x x x- w T w^T wT μ i μ_i μi ) T )^T )T
    \qquad \qquad = ∑ x ∈ X i \sum_{x∈X_i} xXi w T w^T wT( x x x- μ i μ_i μi)( x x x- μ i μ_i μi ) T )^T )T w w w
    \qquad \qquad = w T w^T wT ∑ x ∈ X i \sum_{x∈X_i} xXi( x x x- μ i μ_i μi)( x x x- μ i μ_i μi ) T )^T )T w w w
    \qquad \qquad = w T w^T wT ∑ i \sum_i i w w w
     
    类内方差小,类间距离大
     
    目标函数:
    \qquad \qquad \qquad max J( w w w)= ∣ ∣ w T μ 0 − w T μ 1 ∣ ∣ 2 w T ∑ 0 w + w T ∑ 1 w ||w^Tμ_0-w^Tμ_1||^2\over w^T\sum_0w+w^T\sum_1w wT0w+wT1w∣∣wTμ0wTμ12
     
    \qquad \qquad \qquad \qquad              \;\;\;\;\;\; = ∣ ∣ w T μ 0 − w T μ 1 ∣ ∣ 2 w T ∑ 0 w + w T ∑ 1 w ||w^Tμ_0-w^Tμ_1||^2\over w^T\sum_0w+w^T\sum_1w wT0w+wT1w∣∣wTμ0wTμ12
     
    \qquad \qquad \qquad \qquad              \;\;\;\;\;\; = ∣ ∣ w T ( μ 0 − μ 1 ) ∣ ∣ 2 w T ( ∑ 0 + ∑ 1 ) w ||w^T(μ_0-μ_1)||^2\over w^T(\sum_0+\sum_1)w wT(0+1)w∣∣wT(μ0μ1)2
     
    \qquad \qquad \qquad \qquad              \;\;\;\;\;\; = w T ( μ 0 − μ 1 ) ( μ 0 − μ 1 ) T w w T ( ∑ 0 + ∑ 1 ) w w^T(μ_0-μ_1)(μ_0-μ_1)^Tw\over w^T(\sum_0+\sum_1)w wT(0+1)wwT(μ0μ1)(μ0μ1)Tw
     
    类内散度矩阵(半正定矩阵,对称阵): S w S_w Sw= ∑ 0 \sum_0 0+ ∑ 1 \sum_1 1
    类间散度矩阵(对称阵): S b S_b Sb=( μ 0 μ_0 μ0- μ 1 μ_1 μ1)( μ 0 μ_0 μ0- μ 1 μ_1 μ1 ) T )^T )T
     
    目标函数转化为:
    \qquad \qquad \qquad max J( w w w)= w T S b w w T S w w w^TS_bw\over w^TS_ww wTSwwwTSbw
     
    广义瑞丽商得:J( w w w)的最大值为 S w − 1 S_w^{-1} Sw1 S b S_b Sb的最大特征值
     
    求投影方向 w w w:最重要的是确定 w w w的方向
    此时目标函数优化为:max w T w^T wT S b S_b Sb w w w              \;\;\;\;\;\; s.t. w T w^T wT S w S_w Sww$=1
    拉格朗日:
    \qquad \qquad \qquad L( w w w,λ)= w T w^T wT S b S_b Sb w w w-λ( w T w^T wT S w S_w Sww − 1 ) L 对 -1) L对 1)Lw$求导,并且让其等于0
    \qquad \qquad \qquad S b S_b Sb+ S b T S_b^{T} SbT w w w-λ( S w S_w Sw+ S w T S_w^{T} SwT w w w=0
    \qquad \qquad \qquad \qquad \qquad S b S_b Sb w w w S w S_w Sw w w w \qquad \qquad \qquad (1)

    \qquad S b S_b Sb w w w=( μ 0 μ_0 μ0- μ 1 μ_1 μ1)( μ 0 μ_0 μ0- μ 1 μ_1 μ1 ) T )^T )T w w w

    S b S_b Sb w w w的方向恒为 μ 0 μ_0 μ0- μ 1 μ_1 μ1

    假设 \qquad S b S_b Sb w w w=λ( μ 0 μ_0 μ0- μ 1 μ_1 μ1) \qquad \qquad \qquad (2)

    即让 \qquad λ=( μ 0 μ_0 μ0- μ 1 μ_1 μ1 ) T )^T )T w w w

    (2)带入(1)得:
    \qquad \qquad \qquad w w w= S w − 1 S_w^{-1} Sw1( μ 0 μ_0 μ0- μ 1 μ_1 μ1)

    多分类

    数据集:D={( x 1 x_1 x1, y 1 y_1 y1),( x 2 x_2 x2, y 2 y_2 y2)…( x m x_m xm, y m y_m ym)} \qquad y i y_i yi∈{1,2…N} \qquad x i x_i xi R n × 1 R^{n×1} Rn×1
    N:类数
    n:特征数
    m:样本数量
    m i m_i mi:第i类样本数量
    待求:投影矩阵 W W W={ w 1 w_1 w1, w 2 w_2 w2 w d w_d wd} \qquad w w w R n × d R^{n×d} Rn×d
    μ i μ_i μi:第i类数据集的样本均值
    μ μ μ:整个数据集的样本均值
     
    全局散度矩阵: S t S_t St= S b S_b Sb+ S w S_w Sw
    \qquad \qquad \qquad        \;\;\; = ∑ i = 1 N \sum_{i=1}^{N} i=1N ∑ x ∈ X i \sum_{x∈X_i} xXi( x x x- μ μ μ)( x x x- μ μ μ ) T )^T )T

    类内散度矩阵: S w S_w Sw= ∑ i = 1 N \sum_{i=1}^{N} i=1N ∑ x ∈ X i \sum_{x∈X_i} xXi( x x x- μ i μ_i μi)( x x x- μ i μ_i μi ) T )^T )T

    类间散度矩阵: S b S_b Sb= S t S_t St- S w S_w Sw
    \qquad \qquad \qquad        \;\;\; = ∑ i = 1 N \sum_{i=1}^{N} i=1N ∑ x ∈ X i \sum_{x∈X_i} xXi[( x x x- μ μ μ)( x x x- μ μ μ ) T )^T )T-( x x x- μ i μ_i μi)( x x x- μ i μ_i μi ) T )^T )T]
    \qquad \qquad \qquad        \;\;\; = ∑ i = 1 N \sum_{i=1}^{N} i=1N ∑ x ∈ X i \sum_{x∈X_i} xXi[ x x x x T x^T xT- x x x μ T μ^T μT- μ μ μ x T x^T xT+ μ μ μ μ T μ^T μT- x x x x T x^T xT+ x x x μ i T μ_i^T μiT+ μ i μ_i μi x T x^T xT- μ i μ_i μi μ i T μ_i^T μiT]
    \qquad \qquad \qquad        \;\;\; = ∑ i = 1 N \sum_{i=1}^{N} i=1N ∑ x ∈ X i \sum_{x∈X_i} xXi[- x x x μ T μ^T μT- μ μ μ x T x^T xT+ μ μ μ μ T μ^T μT+ x x x μ i T μ_i^T μiT+ μ i μ_i μi x T x^T xT- μ i μ_i μi μ i T μ_i^T μiT]
    \qquad \qquad \qquad        \;\;\; = ∑ i = 1 N \sum_{i=1}^{N} i=1N[- m i m_i mi μ i μ_i μi μ T μ^T μT- m i m_i mi μ μ μ μ i T μ_i^T μiT+ m i m_i mi μ μ μ μ T μ^T μT+ m i m_i mi μ i μ_i μi μ i T μ_i^T μiT+ m i m_i mi μ i μ_i μi μ i T μ_i^T μiT- m i m_i mi μ i μ_i μi μ i T μ_i^T μiT]
    \qquad \qquad \qquad        \;\;\; = ∑ i = 1 N \sum_{i=1}^{N} i=1N[- m i m_i mi μ i μ_i μi μ T μ^T μT- m i m_i mi μ μ μ μ i T μ_i^T μiT+ m i m_i mi μ μ μ μ T μ^T μT+ m i m_i mi μ i μ_i μi μ i T μ_i^T μiT]
    \qquad \qquad \qquad        \;\;\; = ∑ i = 1 N \sum_{i=1}^{N} i=1N m i m_i mi[- μ i μ_i μi μ T μ^T μT- μ μ μ μ i T μ_i^T μiT+ μ μ μ μ T μ^T μT+ μ i μ_i μi μ i T μ_i^T μiT]
    \qquad \qquad \qquad        \;\;\; = ∑ i = 1 N \sum_{i=1}^{N} i=1N m i m_i mi( μ i μ_i μi- μ μ μ)( μ i μ_i μi- μ μ μ ) T )^T )T
     
    目标函数:
    \qquad \qquad argmax J( w i w_i wi)= ∑ i = 1 d w i T S b w i ∑ i = 1 d w i T S w w i \sum_{i=1}^{d}w_i^TS_bw_i\over \sum_{i=1}^{d}w_i^TS_ww_i i=1dwiTSwwii=1dwiTSbwi
    \qquad \qquad \qquad \qquad          \;\;\;\; = ∑ i = 1 d \sum_{i=1}^{d} i=1d w i T S b w i w i T S w w i w_i^TS_bw_i\over w_i^TS_ww_i wiTSwwiwiTSbwi
    由广义瑞丽熵得:J( w i w_i wi)的最大值为 S w − 1 S_w^{-1} Sw1 S b S_b Sb的最大d个特征值之和

    w i w_i wi
    \qquad \qquad argmax J( w i w_i wi)= ∑ i = 1 d \sum_{i=1}^{d} i=1d w i T S b w i w i T S w w i w_i^TS_bw_i\over w_i^TS_ww_i wiTSwwiwiTSbwi
    \qquad \qquad \qquad \qquad          \;\;\;\; = t r ( W T S b W ) t r ( W T S w W ) tr(W^TS_bW)\over tr(W^TS_wW) tr(WTSwW)tr(WTSbW)

    等价于:
    \qquad \qquad argmax tr( W T W^T WT S b S_b Sb W W W) \qquad \qquad s.t. tr( W T W^T WT S w S_w Sw W W W)=1
    拉格朗日:
    \qquad L(W,∧)=-tr( W T W^T WT S b S_b Sb W W W)+tr(∧( W T {W^T} WT S w S_w Sw W W W-I))
    ∧=diag( λ 1 λ_1 λ1, λ 2 λ_2 λ2 λ d λ_d λd)
    L对W求导,并让其为0:
    \qquad \qquad \qquad S b S_b Sb+ S b T S_b^{T} SbT W W W-∧( S w S_w Sw+ S w T S_w^{T} SwT W W W=0
    \qquad \qquad \qquad \qquad \qquad S b S_b Sb W W W=∧ S w S_w Sw W W W
    对任意 λ i λ_i λi都有:
    \qquad \qquad \qquad \qquad \qquad S b S_b Sb W W W= λ i λ_i λi S w S_w Sw W W W
    => \qquad \qquad \qquad \qquad          \;\;\;\; S w − 1 S_w^{-1} Sw1 S b S_b Sb W W W= λ i λ_i λi W W W

    w i w_i wi S w − 1 S_w^{-1} Sw1 S b S_b Sb的d个最大特征值对应的特征向量

    iris实例

    LDA降维步骤

    1. 计算每类的均值向量
    2. 计算整个样本的均值向量
    3. 计算类内散度矩阵 S w S_w Sw以及类间散度矩阵 S b S_b Sb
    4. 计算 S w − 1 S_w^{-1} Sw1 S b S_b Sb的特征值以及特征向量,选取前d个最大特征值对应的特征向量,组成矩阵W
    5. 对原始数据降维。降维数据Y= W T W^T WTX

    单步

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import datasets
    
    • 1
    • 2
    • 3
    iris=datasets.load_iris()
    #一共三类数据
    x=iris.data
    y=iris.target
    x1=iris.data[:50,:4]
    x2=iris.data[50:100,:4]
    x3=iris.data[100:150,:4]
    #print(x1)
    #print(x2)
    #print(x3)
    print(iris)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    #求每内样本的均值向量
    x1_mean=x1.mean(axis=0)
    x2_mean=x2.mean(axis=0)
    x3_mean=x3.mean(axis=0)
    print(x1_mean)
    print(x2_mean)
    print(x3_mean)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    #求整个数据集的均值向量
    x_mean=x.mean(axis=0)
    print(x_mean)
    print((x1_mean+x2_mean+x3_mean)/3)
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    #计算全局散度矩阵
    x=x-x.mean(axis=0)
    st=np.zeros((4,4))
    print(x)
    print(st)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    for i in range(len(x)):
        st+=np.dot(x[i,np.newaxis].T,x[i,np.newaxis])
    print(st)
    #print(st/150)
    print(np.dot(x.T,x))
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    #计算类内散度矩阵
    x1=x1-x1_mean
    sw1=np.zeros((4,4))
    for i in range(len(x1)):
        sw1+=np.dot(x1[i,np.newaxis].T,x1[i,np.newaxis])
    x2=x2-x2_mean
    sw2=np.zeros((4,4))
    for i in range(len(x2)):
        sw2+=np.dot(x2[i,np.newaxis].T,x2[i,np.newaxis])
    x3=x3-x3_mean
    sw3=np.zeros((4,4))
    for i in range(len(x3)):
        sw3+=np.dot(x3[i,np.newaxis].T,x3[i,np.newaxis])
    print(sw1)
    print(sw2)
    print(sw3)
    sw=sw1+sw2+sw3
    print(sw)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    #计算内间散度矩阵
    sb=st-sw
    print(sb)
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    #svd求sw的逆矩阵
    U,A,V=np.linalg.svd(sw)
    #求A的逆矩阵
    SA=np.linalg.inv(np.diag(A))
    print(SA)
    #计算sw的逆
    VSAU=np.dot(np.dot(V.T,SA),U.T)
    print(VSAU)
    #计算sw-1*sb
    Swb=np.dot(VSAU,sb)
    print(Swb)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    #特征值分解
    val,vector=np.linalg.eig(Swb)
    #只保留实数部分
    val=np.real(val)
    vector=np.real(vector)
    print(val)
    print(vector)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    #排序
    index=np.argsort(-val)
    print(index)
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    #假设降到二维
    print(index[:2])
    Z=vector[:,index[:2]]
    print(Z)
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    #降维后矩阵
    Y=np.dot(x,Z)
    print(Y)
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    #画图
    for i in range(len(y)):
        if y[i]==0:
            plt.scatter(Y[i][0],Y[i][1],c='r',marker='.')
        elif y[i]==1:
            plt.scatter(Y[i][0],Y[i][1],c='b',marker='.')
        else:
            plt.scatter(Y[i][0],Y[i][1],c='g',marker='.')
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    函数

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import datasets
    import random
    
    • 1
    • 2
    • 3
    • 4
    class LinearDiscriminantAnalysis():
        def __init__(self,n_components):
            #特征数
            self.n_components=n_components
            #类别数
            self.classes=0
            #整个数据集的均值向量
            self.X_mean=0
            #特征向量
            self.eig_vectors=0
        def fit_transform(self,X,y):
            #计算样本数量以及特征数
            self.n_samples,self.n_features=X.shape
            #print(self.n_samples)
            #计算类别数,y_index存放相对于classes的类别索引
            self.classes,y_index=np.unique(y,return_inverse=True)
            #计算整体样本的均值向量
            self.X_mean=np.zeros((1,self.n_features))
            self.X_mean=np.copy(X.mean(axis=0))
           # print(self.X_mean)
            #计算全集散度矩阵
            st=np.zeros((self.n_features,self.n_features))
            for i in range(self.n_samples):
                temp=X[i]-self.X_mean
                #st+=np.dot((X[i,np.newaxis]-self.X_mean[0,np.newaxis]).T,(X[i,np.newaxis]-self.X_mean[0,np.newaxis]))
                st+=np.dot(temp[np.newaxis,:].T,temp[np.newaxis,:])
            #print(st)
            #计算每类样本的均值向量
            means=np.zeros((len(self.classes),self.n_features))
            #i代表第几个类别,从0起
            for i in range(len(self.classes)):
                #计算每类个数
                count=0
                for j in range(self.n_samples):
                    if y[j]==self.classes[i]:
                        means[i]+=X[j]
                        count+=1
                means[i]=means[i]/count
            #按类别去中心化,同时求类内散度矩阵
            #print(means)
            sw=np.zeros((self.n_features,self.n_features))
            for i in range(self.n_samples):
                temp=X[i]-means[y_index[i]]
                #sw+=np.dot((X[i,np.newaxis]-means[y_index[i],np.newaxis]).T,(X[i,np.newaxis]-means[y_index[i],np.newaxis]))
                sw+=np.dot(temp[np.newaxis,:].T,temp[np.newaxis,:])
           # print(sw)
            #计算类间散度矩阵
            sb=st-sw
            #SVD求sw的逆矩阵
            U,A,V=np.linalg.svd(sw)
            #计算对角矩阵的逆矩阵
            SA=np.linalg.inv(np.diag(A))
            #计算sw的逆
            VSAU=np.dot(np.dot(V.T,SA),U.T)
            #计算SW-1Sb
            Swb=np.dot(VSAU,sb)
           # print(Swb)
            #特征值分解
            eig_vals,eig_vectors=np.linalg.eig(Swb)
            #特征值排序
            index=np.argsort(-eig_vals)
            #选取特征向量
            if self.n_components==0:
                self.n_components=len(self.classes)-1
            self.vectors=eig_vectors[:,index[:self.n_components]]
            #返回降维后的数据
            return np.dot(X,self.vectors)      
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    iris=datasets.load_iris()
    #打乱数据
    data_size=iris.data.shape[0]
    #生成索引-列表
    index=[i for i in range(data_size)]
    #打乱
    random.shuffle(index)
    #通过打算的索引重新取值,相应的标签也要打乱
    iris.data=iris.data[index]
    iris.target=iris.target[index]
    x=iris.data
    y=iris.target
    lda=LinearDiscriminantAnalysis(2)
    Y=lda.fit_transform(X=x,y=y)
    #画图
    for i in range(len(y)):
        if y[i]==0:
            plt.scatter(Y[i][0],Y[i][1],c='r',marker='.')
        elif y[i]==1:
            plt.scatter(Y[i][0],Y[i][1],c='b',marker='.')
        else:
            plt.scatter(Y[i][0],Y[i][1],c='g',marker='.')
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述
    在这里插入图片描述

    可能会有相反问题,这是特征向量方向的问题。

    sklearn

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import datasets
    from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
    
    • 1
    • 2
    • 3
    • 4
    iris=datasets.load_iris()
    x=iris.data
    y=iris.target
    lda=LinearDiscriminantAnalysis(n_components=2)
    Y=lda.fit(x,y).transform(x)
    #画图
    for i in range(len(y)):
        if y[i]==0:
            plt.scatter(Y[i][0],Y[i][1],c='r',marker='.')
        elif y[i]==1:
            plt.scatter(Y[i][0],Y[i][1],c='b',marker='.')
        else:
            plt.scatter(Y[i][0],Y[i][1],c='g',marker='.')
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

  • 相关阅读:
    上位机图像处理和嵌入式模块部署(树莓派4b的一种固件部署方法)
    开源中文大语言模型汇总
    星域社区原版APP源码/社区交友App源码/动态圈子群聊php源码
    Part 4.2 背包动态规划
    Java教程之自己动手编写清理工具:如何清理MarkDown文档中多余的图片
    docker部署Vaultwarden密码共享管理系统
    数据结构与算法(三) 深度优先搜索
    Java(七)——集合框架---泛型Generic
    演示app基本定位方法(#案例:定位API#演示:ID定位法!#演示:class定位法!#演示:XPATH定位)
    【回溯算法】leetcode 51. N 皇后
  • 原文地址:https://blog.csdn.net/qq_43610614/article/details/126291590