本文主要是介绍单变量线性判别分析分类方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
单变量线性判别分析分类方法
- 单变量线性判别分析
- 用贝叶斯方法进行分类
- 单变量线性判别分析分类
- 参数估计
- 程序实现
- 参考文献
单变量线性判别分析
用贝叶斯方法进行分类
线性判别分析(linear discriminant analysis, LDA)与贝叶斯分类方法的关系十分紧密。我们先来看怎么用贝叶斯方法进行分类。
假设我们有数据集 { ( X 1 , Y 1 ) , ( X 2 , Y 2 ) , ⋯ , } \{(X_1, Y_1), (X_2, \, Y_2), \cdots, \} {(X1,Y1),(X2,Y2),⋯,}。这里 X X X 是自变量, Y Y Y 是因变量,或称为测量量、要预测的变量。 X i X_i Xi可以是一个多维的向量。我们想要把测量到的点(观察点) Y i Y_i Yi 分为 K K K 类中的一类。我们假设每一类的先验概率为 π k \pi_k πk,即如果我们没有其他信息,随机得抽取一个样本点,这个样本点属于第 k k k 类的概率就是 π k \pi_k πk。我们用 f k ( x ) = P ( X = x ∣ Y = k ) \displaystyle f_k (x) = \mathbb{P} (X = x \vert Y = k) fk(x)=P(X=x∣Y=k) 来表示当观察点属于第 k k k 类时,自变量 X X X 的概率密度分布 (当 X X X 的取值为离散的时候,我们就用概率 P ( X = x ∣ Y = k ) \mathbb{P} (X = x \vert Y = k) P(X=x∣Y=k)表示)。
于是,根据Bayes 公式,我们有
P ( Y = k ∣ X = x ) = P ( X = x , Y = k ) P ( X = x ) = P ( X = x , Y = k ) ∑ ℓ = 1 K P ( Y = ℓ ) P ( X = x ∣ Y = ℓ ) = π k f k ( x ) ∑ ℓ = 1 K π ℓ f ℓ ( x ) \begin{aligned} \mathbb{P} (Y = k \vert X = x) &= \frac{\mathbb{P} (X = x, Y = k)}{\mathbb{P} (X = x)} \\ &= \frac{\mathbb{P} (X = x, Y = k)}{\sum_{\ell = 1}^K \mathbb{P}(Y = \ell) \mathbb{P}(X = x \vert Y = \ell)} \\ &= \frac{\pi_k f_k (x) }{\sum_{\ell = 1}^K \pi_{\ell} f_{\ell} (x)} \end{aligned} P(Y=k∣X=x)=P(X=x)P(X=x,Y=k)=∑ℓ=1KP(Y=ℓ)P(X=x∣Y=ℓ)P(X=x,Y=k)=∑ℓ=1Kπℓfℓ(x)πkfk(x)
所以,根据 Bayes 公式,如果我们能够计算出 π k f k ( x ) ∑ ℓ = 1 K π ℓ f ℓ ( x ) \displaystyle \frac{\pi_k f_k (x) }{\sum_{\ell = 1}^K \pi_{\ell} f_{\ell} (x)} ∑ℓ=1Kπℓfℓ(x)πkfk(x) 的值,我们可以比较得出使得 π k f k ( x ) ∑ ℓ = 1 K π ℓ f ℓ ( x ) \displaystyle \frac{\pi_k f_k (x) }{\sum_{\ell = 1}^K \pi_{\ell} f_{\ell} (x)} ∑ℓ=1Kπℓfℓ(x)πkfk(x) 的值最大的那个类 k k k,从而将 X = x X = x X=x 这个数据分到第 k k k类中。为了方便起见,我们用 p k ( x ) p_k (x) pk(x) 来表示 P ( Y = k ∣ X = x ) \mathbb{P} (Y = k \vert X = x) P(Y=k∣X=x)。
如果我们有预先的知识能让我们决定先验分布 π k \pi_k πk,我们可利用预先有的知识来确定 π k \pi_k πk。否则,我们就用样本的频数来估计 π k \pi_k πk。即 π k = n k / n \displaystyle \pi_k = n_k / n πk=nk/n。这里 n k n_k nk 是属于第 k k k 类的样本点的数目。 n n n 是总共的样本数。
而线性判别分析,linear discriminant analysis (LDA) 就提供了一个估计 p k ( x ) p_k (x) pk(x) 的方法。下面我们就来介绍如何用 LDA 来进行贝叶斯公式的估计,从而对数据进行分类。
单变量线性判别分析分类
所谓单变量的线性判别分析,是指 X X X 只有一个变量,即 X X X 是一维的。我们假设 Y Y Y 可以取三个不同的类别。为了估计 p k ( x ) p_k (x) pk(x),我们须要对 f k ( x ) f_{k} (x) fk(x) 有一个估计。这里线性判别分析做了一个假设,即假设 f k ( x ) f_{k} (x) fk(x) 服从一个正态分布。回忆上文, f k ( x ) \displaystyle f_k (x) fk(x) 表示当观察点属于第 k k k 类时,自变量 X X X 的概率密度分布。根据这个假设,我们有
f k ( x ) = 1 2 π exp ( − ( x − μ k ) 2 2 σ k 2 ) f_k (x) = \frac{1}{\sqrt{2 \pi}} \exp \left( - \frac{(x - \mu_k)^2}{2 \sigma_k^2} \right) fk(x)=2π1exp(−2σk2(x−μk)2)
有了对 f k ( x ) f_k (x) fk(x) 的估计,我们便可以计算 p k ( x ) p_k (x) pk(x)。根据上面的公式,我们有 p k ( x ) = π k f k ( x ) ∑ ℓ = 1 K π ℓ f ℓ ( x ) \displaystyle p_k (x) = \frac{\pi_k f_k (x) }{\sum_{\ell = 1}^K \pi_{\ell} f_{\ell} (x)} pk(x)=∑ℓ=1Kπℓfℓ(x)πkfk(x)。代入 f k ( x ) f_{k} (x) fk(x) 的表达式,我们有
p k ( x ) = π k 1 2 π exp ( − ( x − μ k ) 2 2 σ k 2 ) ∑ ℓ = 1 K π ℓ 1 2 π exp ( − ( x − μ ℓ ) 2 2 σ ℓ 2 ) p_k (x) = \frac{\pi_k \frac{1}{\sqrt{2 \pi}} \exp \left( - \frac{(x - \mu_k)^2}{2 \sigma_k^2} \right)}{\sum_{\ell = 1}^K \pi_{\ell} \frac{1}{\sqrt{2 \pi}} \exp \left( - \frac{(x - \mu_\ell)^2}{2 \sigma_\ell^2} \right)} pk(x)=∑ℓ=1Kπℓ2π1exp(−2σℓ2(x−μℓ)2)πk2π1exp(−2σk2(x−μk)2)
如果我们再做一个假设,假设 σ 1 2 = σ 2 2 = ⋯ = σ K 2 \displaystyle \sigma_1^2 = \sigma_2^2 = \cdots = \sigma_K^2 σ12=σ22=⋯=σK2。即对于不同类别的数据,它们对应的 X X X 的分布的方差是相同的。那么我们就有
p k ( x ) = π k 1 2 π exp ( − ( x − μ k ) 2 2 σ 2 ) ∑ ℓ = 1 K π ℓ 1 2 π exp ( − ( x − μ ℓ ) 2 2 σ 2 ) . (1) p_k (x) = \frac{\pi_k \frac{1}{\sqrt{2 \pi}} \exp \left( - \frac{(x - \mu_k)^2}{2 \sigma^2} \right)}{\sum_{\ell = 1}^K \pi_{\ell} \frac{1}{\sqrt{2 \pi}} \exp \left( - \frac{(x - \mu_\ell)^2}{2 \sigma^2} \right)}. \tag{1} pk(x)=∑ℓ=1Kπℓ2π1exp(−2σ2(x−μℓ)2)πk2π1exp(−2σ2(x−μk)2).(1)
对于给定的 X = x X = x X=x,我们找出使得 p k ( x ) p_k (x) pk(x) 最大的那一 k k k 类,就把 x x x 划分到第 k k k 类。
分析公式(1),可以发现分母 ∑ ℓ = 1 K π ℓ 1 2 π exp ( − ( x − μ ℓ ) 2 2 σ 2 ) \displaystyle \sum_{\ell = 1}^K \pi_{\ell} \frac{1}{\sqrt{2 \pi}} \exp \left( - \frac{(x - \mu_\ell)^2}{2 \sigma^2} \right) ℓ=1∑Kπℓ2π1exp(−2σ2(x−μℓ)2) 是与 k k k 无关的。从而我们只需要找到使得分子 π k 1 2 π exp ( − ( x − μ k ) 2 2 σ 2 ) \displaystyle \pi_k \frac{1}{\sqrt{2 \pi}} \exp \left( - \frac{(x - \mu_k)^2}{2 \sigma^2} \right) πk2π1exp(−2σ2(x−μk)2) 最大的那个 k k k 即可。对分子求对数,我们有
arg max k ( p k ( x ) ) = arg max k δ k ( x ) = arg max k ( log ( π k ) + x ⋅ μ k σ 2 − μ k 2 2 σ 2 ) (2) \begin{aligned} \argmax_{k} \left( p_k(x) \right) &= \argmax_{k} \delta_k(x) \\ &= \argmax_k \left( \log(\pi_k) +\frac{x \cdot \mu_k}{\sigma^2} - \frac{\mu_k^2}{2 \sigma^2} \right) \\ \tag{2} \end{aligned} kargmax(pk(x))=kargmaxδk(x)=kargmax(log(πk)+σ2x⋅μk−2σ2μk2)(2)。
由于 δ k ( x ) \delta_k(x) δk(x) 关于 x x x 是线性的,所以我们称之为线性判别分析。
具体地说,如果我们要比较第一类( k = 1 k = 1 k=1) 和第二类 ( k = 2 k =2 k=2),我们代入表达式(2),来看什么情况下 p 1 ( x ) p_1(x) p1(x) 比 p 2 ( x ) p_2(x) p2(x) 大。这里先假设 μ 1 < μ 2 \mu_1 < \mu_2 μ1<μ2,并且我们假设所有类别的先验概率都是一样的,即 π 1 = π 2 = ⋯ = π K \pi_1 = \pi_2 = \cdots = \pi_K π1=π2=⋯=πK。
p 1 ( x ) > p 2 ( x ) ⟺ x ⋅ μ 1 σ 2 − μ 1 2 2 σ 2 > x ⋅ μ 2 σ 2 − μ 2 2 2 σ 2 ⟺ x ⋅ ( μ 1 − μ 2 ) > 1 2 ( μ 1 2 − μ 2 2 ) ⟺ x < 1 2 ( μ 1 + μ 2 ) \begin{aligned} p_1(x) > p_2(x) &\Longleftrightarrow \frac{x \cdot \mu_1}{\sigma^2} - \frac{\mu_1^2}{2\sigma^2} > \frac{x \cdot \mu_2}{\sigma^2} - \frac{\mu_2^2}{2\sigma^2} \\ &\Longleftrightarrow x \cdot (\mu_1 - \mu_2) > \frac{1}{2} (\mu_1^2 - \mu_2^2) \\ &\Longleftrightarrow x < \frac{1}{2} (\mu_1 + \mu_2) \end{aligned} p1(x)>p2(x)⟺σ2x⋅μ1−2σ2μ12>σ2x⋅μ2−2σ2μ22⟺x⋅(μ1−μ2)>21(μ12−μ22)⟺x<21(μ1+μ2)
也就是说,当 x x x 的值小于 μ 1 \mu_1 μ1 与 μ 2 \mu_2 μ2 的平均值时, x x x 就划分为第一类;反之当 x x x 的值大于 μ 1 \mu_1 μ1 与 μ 2 \mu_2 μ2 的平均值时,就划分为第二类。
如果我们有多余两个的类别的数目( K > 2 K > 2 K>2),我们须要计算 p 1 ( x ) , p 2 ( x ) , ⋯ , p K ( x ) p_1(x), \, p_2(x), \cdots, \, p_K(x) p1(x),p2(x),⋯,pK(x),找到使 p k ( x ) p_k(x) pk(x) 最大的那个 k k k。
参数估计
实际问题中,大多数情况下我们是不知道 μ 1 , μ 2 , ⋯ , μ K \mu_1, \mu_2, \cdots, \, \mu_K μ1,μ2,⋯,μK 以及 σ 2 \sigma^2 σ2 的,这就要求我们对 μ 1 , μ 2 , ⋯ , μ K \mu_1, \mu_2, \cdots, \, \mu_K μ1,μ2,⋯,μK 以及 σ 2 \sigma^2 σ2 作出估计。
我们用如下方法进行估计 [1]:
μ ^ k = 1 n k ∑ i : y i = k x i σ ^ 2 = 1 n − K ∑ k = 1 K ∑ i : y i = k ( x i − μ ^ k ) 2 \begin{aligned} \hat{\mu}_k &= \frac{1}{n_k} \sum_{i: y_i = k} x_i \\ \hat{\sigma}^2 &= \frac{1}{n - K} \sum_{k = 1}^K \sum_{i: y_i = k} (x_i - \hat{\mu}_k)^2 \end{aligned} μ^kσ^2=nk1i:yi=k∑xi=n−K1k=1∑Ki:yi=k∑(xi−μ^k)2
这里 n n n 是样本点的个数, n k n_k nk 是第 k k k 类的样本点的数目。
程序实现
假设 K = 3 K =3 K=3,我们的样本数据来自于三个不同的正态分布,如下图所示:
黑色的虚线和红色的虚线分别代表根据LDA 的线性判别公式得到的分类边界(decision boundary)。
我们根据三个不同的正态分布生成样本数据点。
num_points_each_category = 10
x1_sample = np.random.normal(mu_vec[0], 1, (num_points_each_category, 1))
x2_sample = np.random.normal(mu_vec[1], 1, (num_points_each_category, 1))
x3_sample = np.random.normal(mu_vec[2], 1, (num_points_each_category, 1))
x1_label = np.zeros((num_points_each_category, 1)) + 1 # generate the label value for category 1
x2_label = np.zeros((num_points_each_category, 1)) + 2 # generate the label value for category 2
x3_label = np.zeros((num_points_each_category, 1)) + 3 # generate the label value for category 3# Make x_i of shape (num_points_each_category, 2), with x_i[:,0] being the data value
# and x_i[:,1] the category label
x1 = np.hstack((x1_sample, x1_label))
x2 = np.hstack((x2_sample, x2_label))
x3 = np.hstack((x3_sample, x3_label))# Combine them into one ndarray
sample = np.vstack((x1, x2, x3))
sample
的 shape 为 ( m m m, 2)。这里 m m m 是所有数据点的个数。样本点生成之后,我们可以根据一下程序对样本点进行分类。
class LDA:def __init__(self, num_categories, pi_vector, mu_vector, variance):"""num_categories is the number of total categories. vairance is the common distribution variance for all categories.pi_vector is the vector containing the prior distribution forall categories. len(pi_vector) = num_categoriesmu_vector is the vector containing the mean value for eachcategory. len(mu_vector) = num_categories."""self.num_categories = num_categoriesself.variance = varianceself.pi_vector = pi_vectorself.mu_vector = mu_vectorself.estimated_mu_vector = []self.estimated_variance = 0def discriminantFormula(self, x, pi_k, mu_k, var):"""Calculate the value of the \delta_k(x) function given x. The meaning of \delta_k(x) function isdefined in the text. pi_k is the prior distribution for the kth category.mu_k is the mean value of the kth category."""delta_k_at_x = x * mu_k / var + \np.log(pi_k) - (mu_k ** 2) / (2 * var)return delta_k_at_xdef find_best_k(self, x, using_estimated_mu_and_var=True):"""Find the best category that makes \delta_k(x) the largest.x is the value of the sample data point."""cur_max = -float('inf')candi = -1for i in range(self.num_categories):if using_estimated_mu_and_var:cur = self.discriminantFormula(x, self.pi_vector[i], self.estimated_mu_vector[i], self.estimated_variance)else:cur = self.discriminantFormula(x, self.pi_vector[i], self.mu_vector[i], self.variance)if cur > cur_max:candi = icur_max = curreturn candi + 1 # we add 1 because the index starts from 0def get_estimation_mu_variance(self, sample):"""In reality we need to estimate the mu_vector and the commonvariance from the sample. sample has a dimension of (m, 2). m is the total number of data points. sample[:,0] is the valueof the data points, sample[:,1] is the category label for each data point (the label starts from 1). """m = sample.shape[0]mu_estimated = [0 for _ in range(self.num_categories)]variance_total = 0for i in range(self.num_categories):category_i_data = sample[sample[:,1] == (i + 1)]mu_estimated[i] = np.mean(category_i_data[:,0])variance_total += np.sum((category_i_data[:,0] - mu_estimated[i]) ** 2)variance_estimated = variance_total / (m - self.num_categories)self.estimated_mu_vector= mu_estimatedself.estimated_variance = variance_estimatedreturn (mu_estimated, variance_estimated)def calculate_accuracy(self, sample: 'np.ndarray', using_estimated_mu_and_var=True):"""We calculate the accuracy of the LDA classification method. Heresample is an np.ndarray type with the dimension (m, 2). m is the total number of points in sample. """m = sample.shape[0]predicted = [-1 for _ in range(m)]for i in range(m):cur_predicted = self.find_best_k(sample[i, 0], using_estimated_mu_and_var)predicted[i] = cur_predictedreturn np.sum(np.array(predicted) == sample[:,1]) / m
对样本 sample
进行分析如下。
a = LDA(num_categories=3, pi_vector=[1/3, 1/3, 1.3], mu_vector=mu_vec, variance=1)
estimated_mu_vector, estimated_variance = a.get_estimation_mu_variance(sample)
a.calculate_accuracy(sample, using_estimated_mu_and_var=True)
最终作图如下:
plt.figure(figsize=(10, 8))
plt.plot(x1[:,0], np.zeros(num_points_each_category), 's', x2[:,0], np.zeros(num_points_each_category), 'v',x3[:,0], np.zeros(num_points_each_category), 'o', markerfacecolor='none', markersize=20, markeredgewidth=2)
# plt.scatter(x2_sample, np.zeros(10), 'v', markerfacecolor='none', markersize=20, linewidth=8)
# plt.scatter(x3_sample, np.zeros(10), 'o', markerfacecolor='none', markersize=20, linewidth=8)
plt.vlines(1, -0.1, 0.1, color='red',linestyles='--', linewidth=4)
plt.vlines(-1, -0.1, 0.1, color='black',linestyles='--', linewidth=4)
plt.vlines(np.mean([estimated_mu_vector[1], estimated_mu_vector[2]]), -0.1, 0.1, color='red',linestyles='-', linewidth=4)
plt.vlines(np.mean([estimated_mu_vector[0], estimated_mu_vector[1]]), -0.1, 0.1, color='black',linestyles='-', linewidth=4)
plt.ylim(-0.1, 0.1)
plt.xlabel(r"x", fontsize=36)
#plt.ylabel("$y$", fontsize=36)
plt.xticks(fontsize=24)
plt.yticks([])
图中虚线为根据理论的样本分布函数期望计算得到的分类边界,实线则为根据实际样本点计算得到的分类边界。有了边界值,如果在给我们一个样本点 x x x,我们就可以根据分类边界对 x x x 进行分类。
参考文献
[1] An introduction to statistical learning: with applications in R, Gareth James, Daniela Witten, Trevor Hastie, and Robert Tibshirani, Springer.
这篇关于单变量线性判别分析分类方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!