Fisher 线性分类器的设计与实现

 

注:博客中的样本表示  都是一列,不是一行

实验代码:

# -*- coding: utf-8 -*-
"""
Created on Wed Apr 17 19:50:39 2019

@author: LCCFM
"""

# -*- coding: utf-8 -*-


# 二分类问题 w1 w2

import math
import numpy as np
import matplotlib.pyplot as plt

def fisher(w1, w2):    
    #将行向量转置为列向量
    w1=w1.T
    w2=w2.T

    sz1 = np.size(w1,1)
    sz2 = np.size(w2,1)
    
    #  1.求wi均值
    m1 = np.mean(w1, axis=1)
    m2 = np.mean(w2, axis=1)
  
    # 2.计算样本内离散度 Si 和总类内离散度矩阵 Sw
    s1 = np.zeros((w1.shape[0],w1.shape[0]))
    n, m = w1.shape
    for i in range(m):
        tmp = w1[:,i] - m1
        s1 = s1 + tmp * tmp.T

    s2 =  np.zeros((w2.shape[0],w2.shape[0]))
    n, m = w2.shape
    for i in range(m):
        tmp = w2[:,i] - m2
        s2 = s2 + tmp * tmp.T
    sw = (sz1*s1 + sz2*s2)/(sz1+sz2)

    # 3.计算样本间离散度 sb
    sb = (m1 - m2) * (m1 - m2).T

    # 4.计算w_star
    w_star = np.linalg.inv(sw) * (m1-m2)
    res1=0
    for i in range(sz1):
        res1 = res1 + w1[:,i].T*w_star
    res1/=sz1
    
    res2=0
    for i in range(sz2):
        res2 = res2 +w2[:,i].T*w_star
    res2/=sz2
    
    '''
    # 4.另外一种计算 w_star的方式,
    #求sw^(-1)*sb 的特征值,特征向量
    t = np.linalg.inv(sw)*sb
    v, Q = np.linalg.eig(t)
    
    #找到最大特征值对应的特征向量
    res_pos = v.argmax(axis=0)
    w_star2 = Q[:,res_pos]
    
    #计算 sw^(-1/2) 
    v2,Q2 =np.linalg.eig(sw)
    
    v_half=np.zeros((v2.size,v2.size))
    for i in range(v2.size):
        v_half[i][i]=math.sqrt(v2[i])
    sw_half=Q2 * v_half*(Q2**(-1))
    
    #最后的结果为 sw^(-1/2)*w_star
    sw_half=sw_half**(-1)
    w_star2=sw_half*w_star2

    res1=0
    for i in range(sz1):
        res1 = res1 + w1[:,i].T*w_star2
    res1/=sz1
    
    res2=0
    for i in range(sz2):
        res2 = res2 +w2[:,i].T*w_star2
    res2/=sz2
    '''
    return -(res1*sz1+res2*sz2)/(sz1+sz2), w_star


def get_res(X, w0 ,w_star):
    res = X * w_star + w0
    if res >=0:
        print('合格')
    else:
        print('不合格')
    
    
def get_line(w, w0):
    # 换两类之间的分界线
    w = np.array(w)
    x = np.linspace(1, 5, 50)
    y = -w[0,0]*x/w[1,0]-w0/w[1,0]
    y=y.reshape(-1,1)#将行向量转置
    return x, np.array(y)

def show_fig(w):
     fig = plt.figure()
     ax1 = fig.add_subplot(111)
     ax1.scatter(np.array(w1[:,0]), np.array(w1[:,1]),c='r')
     ax1.scatter(np.array(w2[:,0]), np.array(w2[:,1]),c='y')
     ax1.plot(wx,wy) 
     ax1.scatter(np.array(w[0,0]), np.array(w[0,1]),c='b')
     plt.show()

if __name__ == '__main__':
  
    w1 = np.mat([[2.95, 6.63], [2.53, 7.79], [3.57, 5.65],[3.16,5.47]])
    w2 = np.mat([[2.58, 4.46], [2.16, 6.22], [3.27, 3.52]])
    
    w0,w_star=fisher(w1, w2)
    
    fig = plt.figure()
    ax1 = fig.add_subplot(111)
    ax1.scatter(np.array(w1[:,0]), np.array(w1[:,1]),c='r')
    ax1.scatter(np.array(w2[:,0]), np.array(w2[:,1]),c='y')
    
    wx,wy=get_line(w_star, w0)
    
    #显示分类情况
    ax1.plot(wx,wy)    
    plt.show()

    #输入样例
    while True:       
        n1,n2= map(float,input().split())
        #print(n1,n2)
        w=np.mat([n1,n2])
        show_fig(w)
        get_res(w,np.array(w0),w_star)
        
    

 

     性判别

 

# -*- coding: utf-8 -*-
"""
Created on Thu Apr 18 17:01:50 2019

@author: LCCFM
"""

import os
import cv2                #导入opencv库
import numpy as np 

def get_w(file_path):
    #读取文件夹下所有文件
    #print(file_path)
    
    #创建一个空矩阵
    train_set = np.zeros(shape=[1,32*32])
    
    for filename in os.listdir(file_path):              #listdir的参数是文件夹的路径
        #print (filename)                                  #此时的filename是文件夹中文件的名称
        img = cv2.imread(file_path+'/'+filename,cv2.IMREAD_GRAYSCALE)   #读取图片,第二个参数表示以灰度图像读入
        #res= cv2.resize(img,(28,28))              #对图片进行缩放,第一个参数是读入的图片,第二个是制定的缩放大小
        #cv2.imshow('img',img)
        #cv2.waitKey(0)
        res=img
        sp = img.shape
        #print(sp)
        res_1 = res.reshape(1,sp[0]*sp[1])       #将表示图片的二维矩阵转换成一维
        res_2= res_1.tolist()     #将numpy.narray类型的矩阵转换成list
        #train_set.append(res_2)   #将list添加到已有的list中
        train_set=np.row_stack((train_set,res_2))
        #print(train_set)
    return train_set

'''
def get_res(w,res1,res2,w_star):
    #print(res1-w.T*w_star,res2-w.T*w_star)
    if abs(res1-w.T*w_star)<abs(res2-w.T*w_star):
      print('第一个人')
    else:
      print('第二个人')
'''      

def get_res(X, w0 ,w_star):
    res = X * w_star + w0
    if res >=0:
        print('第一个人')
    else:
        print('第二个人')

def fisher(w1, w2):    
    #将行向量转置为列向量
    w1=w1.T
    w2=w2.T

    sz1 = np.size(w1,1)
    sz2 = np.size(w2,1)
    
    #  1.求wi均值
    m1 = np.mean(w1, axis=1)
    m2 = np.mean(w2, axis=1)
  
    # 2.计算样本内离散度 Si 和总类内离散度矩阵 Sw
    s1 = np.zeros((w1.shape[0],w1.shape[0]))
    n, m = w1.shape
    for i in range(m):
        tmp = w1[:,i] - m1
        s1 = s1 + tmp * tmp.T

    s2 =  np.zeros((w2.shape[0],w2.shape[0]))
    n, m = w2.shape
    for i in range(m):
        tmp = w2[:,i] - m2
        s2 = s2 + tmp * tmp.T
    sw = (sz1*s1 + sz2*s2)/(sz1+sz2)

    # 3.计算样本间离散度 sb
    sb = (m1 - m2) * (m1 - m2).T

    # 4.计算w_star
    w_star = np.linalg.inv(sw) * (m1-m2)
    res1=0
    for i in range(sz1):
        res1 = res1 + w1[:,i].T*w_star
    res1/=sz1
    
    res2=0
    for i in range(sz2):
        res2 = res2 +w2[:,i].T*w_star
    res2/=sz2
    
    '''
    # 4.另外一种计算 w_star的方式,
    #求sw^(-1)*sb 的特征值,特征向量
    t = np.linalg.inv(sw)*sb
    v, Q = np.linalg.eig(t)
    
    #找到最大特征值对应的特征向量
    res_pos = v.argmax(axis=0)
    w_star2 = Q[:,res_pos]
    
    #计算 sw^(-1/2) 
    v2,Q2 =np.linalg.eig(sw)
    
    v_half=np.zeros((v2.size,v2.size))
    for i in range(v2.size):
        v_half[i][i]=math.sqrt(v2[i])
    sw_half=Q2 * v_half*(Q2**(-1))
    
    #最后的结果为 sw^(-1/2)*w_star
    sw_half=sw_half**(-1)
    w_star2=sw_half*w_star2

    res1=0
    for i in range(sz1):
        res1 = res1 + w1[:,i].T*w_star2
    res1/=sz1
    
    res2=0
    for i in range(sz2):
        res2 = res2 +w2[:,i].T*w_star2
    res2/=sz2
    '''
    return -(res1*sz1+res2*sz2)/(sz1+sz2), w_star

if __name__ == '__main__':
    #D:\学习\大三\AI\expriment\Two\2\Train
    w1 = get_w(r'D:/STUDY/Three/AI/expriment/Two/2/Train/1')
    w2 = get_w(r'D:/STUDY/Three/AI/expriment/Two/2/Train/2')
    w1 = np.delete(w1,1,axis=0)
    w2 = np.delete(w2,1,axis=0)
    
    w0, w_star=fisher(np.mat(w1), np.mat(w2))
    
    
    file_path='./Test'
    for filename in os.listdir(file_path):              #listdir的参数是文件夹的路径
        print (filename)                                  #此时的filename是文件夹中文件的名称
        img = cv2.imread(file_path+'/'+filename,cv2.IMREAD_GRAYSCALE)   #读取图片,第二个参数表示以灰度图像读入
        #res= cv2.resize(img,(28,28))              #对图片进行缩放,第一个参数是读入的图片,第二个是制定的缩放大小
        res=img
    
        sp =img.shape
        res_1 = res.reshape(1,sp[0]*sp[1])       #将表示图片的二维矩阵转换成一维
        res_2= res_1.tolist()     #将numpy.narray类型的矩阵转换成list
        get_res(np.mat(res_2), w0 ,w_star)
    

 

知识链接:https://www.cnblogs.com/pinard/p/6244265.html

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值