机器学习:多维二分类线性判别分析(LDA)实例,如何从多个广义特征向量中求解

最近小白在啃西瓜书,一边啃一边啃一边实践,因此基于LDA顺手做了一个实例。数据来源是machinelearningmastery.com数据库中的钞票数据集,txt数据文本下载地址:http://t.cn/Rf8GdQo,有兴趣的小伙伴也可以用这个数据试试。

数据不多,一共有 1372 个观察值,4个输入变量和1个输出变量。变量名如下:

小波变换图像(连续)

小波偏斜变换图像(连续)

小波峰度变换图像(连续)

图像熵(连续)。

类(0 为真钞,1 为假钞)

很明显是一个四个变量,也就是四维的线性判别分析问题,与西瓜书上的二维多少有些不一样。最关键的问题就是用python.linalg.eig求完广义特征值后如何选择的问题,笔者在此程序中直接选择了最大广义特征值对应的特征向量作为w的解,依据是西瓜书上的原话“W的闭式解是d'个最大非零广义特征值对应的特征向量组成的矩阵,d'<=N-1”,其中N代表分类数,因为该数据是二分类数据,所以只需选择最大广义特征值对应的特征向量即可。至于二分类以上,有多个最大特征向量,该如何求解的问题,暂时还没有想明白,若有大佬知道可在底下留言告知。

制作这个实例,按照0.7的比例划分出训练集,剩下0.3作为测试集,因为只是一个练习实例,也没有设置验证集,只用最简单的准确率来判定这个LDA训练出的模型的准确性,结果尝试运行了十几次,每一次的准确率都在95%之上,还算不错,代码贴在下面。

import numpy as np
import pandas as pd
from scipy import linalg

def split_data(data,split_radio):
    shuffle = np.random.permutation(data)
    test_size = int(len(data)*split_radio)
    training_data = shuffle[0:test_size]
    test_data = shuffle[test_size:]
    return training_data,test_data

with open ("data_banknote_authentication.txt") as file:
    data = file.readlines()
    number_line = len(data)
for i in range(number_line):
    data[i] = data[i].strip()
    data[i] = data[i].split(",")
data = np.array(data) #提取data并转化为ndarray

training_data,test_data = split_data(data,0.7)
training_data_x1,training_data_x2 = [],[]
for i in training_data:
    if i[4] == "0":
        training_data_x1.append(i[0:4])
    else:
        training_data_x2.append(i[0:4])
training_data_x1 = np.array(training_data_x1)
training_data_x2 = np.array(training_data_x2) #去除了labels且分好类的训练集
training_data_x1 = training_data_x1.astype(np.float32)
training_data_x2 = training_data_x2.astype(np.float32)
training_data = np.delete(training_data,-1,axis=1)
training_data = training_data.astype(np.float32)


test_data_labels = []
for i in test_data:
    test_data_labels.append(i[4])
test_data_labels = [int(i) for i in test_data_labels]
test_data = np.delete(test_data,-1,axis=1)#去除了labels的测试集
test_data = test_data.astype(np.float32)

#LDA开始
u = np.mean(training_data,axis=0)
u_0 = np.mean(training_data_x1,axis=0)
u_1 = np.mean(training_data_x2,axis=0)

S_w = np.cov(training_data_x1, rowvar=False) + np.cov(training_data_x2, rowvar=False)
S_b = len(training_data_x1)*np.dot((u_0-u).reshape(-1,1),(u_0-u).reshape(1,-1))+\
      len(training_data_x2)*np.dot((u_1-u).reshape(-1,1),(u_1-u).reshape(1,-1))

eig = linalg.eig(S_b,S_w)
r = eig[0]
r = list(r)
r_enumerate = enumerate(r)
r_max = max(r)
order = []
for i in r_enumerate:
    if i[1] == r_max:
        order.append(i[0])
w = eig[order[0]+1]
w1 = w[:,0]


m = 0
for i in training_data_x1:
    m += np.dot(w1,i)

x0 = m/len(training_data_x1)

n = 0
for i in training_data_x2:
    n += np.dot(w1,i)
x1 = n/len(training_data_x2)

#开始测试集测试,计算准确率
right = 0
test_labels = []
for i in test_data:
    test_i = np.dot(w1,i)
    distance_0 = abs(test_i-x0)
    distance_1 = abs(test_i-x1)
    if distance_0 >= distance_1:
        test_labels.append(1)
    else:
        test_labels.append(0)

for i in range(len(test_data_labels)):
    if test_data_labels[i] == test_labels[i]:
        right += 1

accuracy = right/len(test_labels)
print(accuracy)
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值