Fisher與Knn對(duì)比(模式識(shí)別2)

KNN算法總結(jié)-1.png
KNN算法總結(jié)-2.png
KNN算法總結(jié)-3.png
KNN算法總結(jié)-4.png
KNN算法總結(jié)-5.png
KNN算法總結(jié)-6.png
KNN算法總結(jié)-7.png
KNN算法總結(jié)-8.png
KNN算法總結(jié)-9.png

程序

main.py

# %%
import numpy as np
from Fisher import Fisher
import process_data as pd
import Eval
import time
import os
from Knn import KNN
import plot


flag=0#0usps,1=sonar
# To->main
if flag:
    file_name = './Sonar.csv'
else:
    file_name = './usps_3&8.csv'
### t0=time.time()
#


cross_validation_number = 8
class_number = 2
k=9

# dataset = dict()

def fff():
    color=['r','b']
    data = dict(x=[[], []], y=[[], []])
    val_data = dict(x=[[], []], y=[[], []])
    Pred_True = [0] * class_number
    pred_num=[0,0]
    L = [0, 0]
    last_j=float('-inf')

    datas, L[0], L[1], Lall = pd.read_datas(file_name)
    data_block = pd.split_datas(datas, cross_validation_number)
    i = 0
    for cla, val in data_block:
        # print(i)
        i += 1
        for j in range(len(cla)):
            (data['x'][j], data['y'][j], val_data['x'][j], val_data['y'][j]) = (
            cla[j][:, :-1], cla[j][:, -1:], val[j][:, :-1], val[j][:, -1:])
        myfisher = Fisher(L[0], L[1], Lall, data)

        W = myfisher.W_Direction()  # 投影參數(shù)
        J=Eval.simple_Fisher_Friterion(W,myfisher.between_class_scatter_matrix())#評(píng)估一下投影效果拆座,并更新投影向量
        if J>last_j:
            last_j=J
            W_great=W
        W0 = myfisher.OneKey_W0(W)  # 閾值
        # %%
        for j in range(class_number):
            predict_y = myfisher.Pred_result(W, val_data['x'][j], W0)
            # print(predict_y)
            # 畫圖
            plot.draw(predict_y,color[j])
            pred_num[j]+=len(val_data['x'][j])
            Pred_True[j] += Eval.Comp_as1(predict_y)
        plot.show(str(i))
        # print(time.time()-t0)
    print('  預(yù)測(cè)->>    第1類   第2類   全部')
    for j in range(class_number):
        print('實(shí)際第{0}類    {1}     {2}      {3}'.format(j+1,Pred_True[j],pred_num[j]-Pred_True[j],pred_num[j]))
    print('mixed_accuracy:%f' % ((Pred_True[0]+pred_num[1]-Pred_True[1])/(pred_num[0]+pred_num[1])))

    # print('評(píng)價(jià)函數(shù)最大的W保存在',os.path.abspath(Eval.w_filename))
    # Eval.save_par(W_great)
    pass

def kkk():
    data = dict(x=[[], []], y=[[], []])
    val_data = dict(x=[[], []], y=[[], []])
    Pred_True = [0] * class_number
    pred_num = [0, 0]
    L = [0, 0]

    datas, L[0], L[1], Lall = pd.read_datas(file_name)
    data_block = pd.split_datas(datas, cross_validation_number)

    for cla, val in data_block:
        for j in range(len(cla)):
            (data['x'][j], data['y'][j], val_data['x'][j], val_data['y'][j]) = (
                cla[j][:, :-1], cla[j][:, -1:], val[j][:, :-1], val[j][:, -1:])
        myknn=KNN(data,k)
        for i in range(class_number):

            predict_y = list()
            for x in val_data['x'][i]:
                predict_y.append(myknn.predict(x))
            pred_num[i] += len(predict_y)  # 預(yù)測(cè)總數(shù)量
            Pred_True[i] += Eval.Comp_as1(predict_y)
        pass
    print('     預(yù)測(cè)第1類   預(yù)測(cè)第2類   全部')
    for j in range(class_number):
        print('實(shí)際第{0}類    {1}     {2}      {3}'.format(j + 1, Pred_True[j], pred_num[j] - Pred_True[j], pred_num[j]))
    print('mixed_accuracy:%f' % ((Pred_True[0] + pred_num[1] - Pred_True[1]) / (pred_num[0] + pred_num[1])))
if __name__ == '__main__':
    fff()
    # kkk()
    pass

'''
sonar
  預(yù)測(cè)      第1類   第2類   全部
實(shí)際第1類    63     33      96
實(shí)際第2類    36     72      108
mixed_accuracy:0.661765

usps_3&8
  預(yù)測(cè)      第1類   第2類   全部
實(shí)際第1類    789     31      820
實(shí)際第2類    20     680      700
mixed_accuracy:0.966447
'''
'''
     預(yù)測(cè)第1類   預(yù)測(cè)第2類   全部
實(shí)際第1類    44     46      90
實(shí)際第2類    43     67      110
mixed_accuracy:0.555000

     預(yù)測(cè)第1類   預(yù)測(cè)第2類   全部
實(shí)際第1類    803     17      820
實(shí)際第2類    10     690      700
mixed_accuracy:0.982237
'''

Fisher.py

import numpy as np

x = []  # n*d
w = []  # d*1
y = []  # 0*n

x = np.array(x)
w = np.array(w)
y = np.array(y)


def within_class_scatter_matrix(x, m):
    '''

    :param x: n*d->n*d*1
    :param m: d*1->1*d*1
    :return:類內(nèi)離散度矩陣 d*d
    '''
    x = x[:, :, np.newaxis]
    m_d = len(m)
    m = m[np.newaxis, :, :]  # 1*d*1
    n, d = np.shape(x)[0], np.shape(x)[1]
    assert d == m_d
    temp = x - m
    temp_tran = np.transpose(temp, (0, 2, 1))  # n*1*d
    # print(list(map(np.shape,[x-m,x_transpose-m_transpose])))
    # 三維點(diǎn)乘變循環(huán)
    s = []
    for a, b in zip(temp, temp_tran):
        s.append(np.dot(a, b))
    s = np.array(s)
    s = np.sum(s, 0)
    assert s.shape == (d, d)
    return s


def pooled_within_class_scatter_matrix(wcsm1, wcsm2, L1, L2, Lall):
    '''

    :param wcsm1: d*d
    :param wcsm2:
    :return: 總類內(nèi)離散度矩陣 d*d
    '''
    return (L1 * wcsm1 + L2 * wcsm2) / Lall





def projective_mean(w, m):
    '''

    :param w: 投影方向 d*1
    :param m: 類均值向量 d*1
    :return:投影后的均值 0*0 scalar
    '''

    def pred_y(x, w):
        '''
        :param x: n*d
        :param w: d*1
        :return: 預(yù)測(cè)值 0*n
        '''
        return x.dot(w).ravel()

    assert np.shape(w) == np.shape(m)
    # print('w:',np.transpose(w).shape,'m',m.shape)
    # print(pred_y(np.transpose(w),m)[0])
    return pred_y(np.transpose(w), m)[0]


def projective_within_class_scatter_matrix(y, M):
    '''

    :param y: 投影后的樣本0*n
    :param M: 均值向量投影后 0*0
    :return:投影后類內(nèi)離散度0*0 scalar
    '''
    M = np.array([M])  # 0*1
    return pow(np.linalg.norm(y - M), 2)


def projective_between_class_scatter_matrix(m1, m2):
    '''

    :param m1: 投影后均值
    :param m2:
    :return: 投影后類間離散度0*0 scalar
    '''
    return pow((m1 - m2), 2)


def w_direction(S_W, m1, m2):
    '''

    :param S_W:總類內(nèi)離散度矩陣 d*d
    :param m1: 類均值向量 d*1
    :param m2:
    :return: d*1 投影參數(shù)(大小無所謂)
    '''
    # print(S_W**-1)
    # print()
    return np.dot(np.linalg.inv(S_W), (m1 - m2))


def W0(m1, m2):
    '''
    不考慮先驗(yàn)概率
    :param m1: scalar 投影后均值
    :param m2:
    :return: 閾值
    '''
    return -(m1 + m2) / 2

class Fisher(object):
    def __init__(self, L1, L2, Lall, data):
        self.L1 = L1
        self.L2 = L2
        self.Lall = Lall
        self.M = [[], []]  # 均值向量
        self.M[0], self.M[1] = map(self.__class_mean_vector, [data['x'][0], data['x'][1]])
        self.data_x=data['x']

    def __class_mean_vector(self, x):
        '''

        :param x:n*d
        :return:類均值向量 d*1
        '''
        return np.transpose(np.mean(x, 0, keepdims=True))

    def Pred_result(self, w, x, w0):
        '''

        :param w:投影參數(shù)d*1
        :param x: n*d
        :param w0: 0*0
        :return: 決策結(jié)果 (n,)
        '''
        w0 = np.array([w0])
        temp = np.dot(x, w)
        return temp.ravel() + w0

    def W_Direction(self):
        Sw1, Sw2 = within_class_scatter_matrix(self.data_x[0], self.M[0]), within_class_scatter_matrix(self.data_x[1], self.M[1])
        SW = pooled_within_class_scatter_matrix(Sw1, Sw2, self.L1, self.L2, self.Lall)
        W = w_direction(SW, self.M[0], self.M[1])
        return W

    def OneKey_W0(self, W):
        m1, m2 = projective_mean(W, self.M[0]), projective_mean(W, self.M[1])
        return W0(m1, m2)

    def between_class_scatter_matrix(self):
        '''

        :param m1: 第一類均值向量 d*1
        :param m2: 第二類均值向量
        :return: 類間離散度矩陣 d*d
        '''
        m_ = self.M[0] - self.M[1]

        return np.dot(m_, np.transpose(m_))

Knn.py

import numpy as np

class KNN(object):
    def __init__(self,data,K):
        '''

        :param data: (n,d)
        '''
        self.data_x=np.concatenate((data['x'][0],data['x'][1]),0)
        self.data_y=np.concatenate((data['y'][0],data['y'][1]),0)
        self.k=K
        #參與投票者必須小于全體投票者
        assert self.k<=len(self.data_x)
        pass



    def predict(self,x):
        '''

        :param x:
        :return:
        '''
        def candidate( m):
            j = m  # 工作索引

            c = ballot[m]  # 候選/被比較的候選眾數(shù)
            count = 1  # 計(jì)數(shù)器

            while j < n and count > 0:
                j += 1
                # 如果現(xiàn)在的j使得列表越界习瑰,可以執(zhí)行else的操作并退出循環(huán)
                try:
                    ballot[j]
                except IndexError:
                    count -= 1
                    continue
                # 有一個(gè)一樣計(jì)數(shù)器+1
                if ballot[j] == c:
                    count += 1
                # 不一樣的抵消,計(jì)數(shù)器-1
                else:
                    count -= 1
            # 工作索引和長(zhǎng)度一樣官撼,走完序列,返回當(dāng)前剩余的候選眾數(shù)
            if j == n:
                return c
            else:
                return candidate(j + 1)
            pass
        '''

        :param x: (1,d)
        :return:(k,)
        '''
        distance=np.linalg.norm((self.data_x-x),axis=1)
        position=np.argsort(distance)[:self.k]
        ballot=list()
        for p in position:
            ballot.append(self.data_y[p][0])
        # print(ballot)
        n=self.k
        result=candidate(0)
        return result

Eval.py

import json
import numpy as np


#To->Eval
w_filename='w.json'

def save_par(w):
    with open(w_filename,'w') as fp:
        json.dump(list(w.ravel()),fp)

def load_par():
    with open(w_filename,'r') as fp:
        return np.array(json.load(fp))[:,np.newaxis]

def Comp_as1(y):
    # y=(y>0.0 if label>0 else y<=0.0)
    if isinstance(y,list):
        y=np.array(y)
    y= y>0.0
    return np.sum(y)

def simple_Fisher_Friterion(w,S_b):
    '''
    Fisher簡(jiǎn)化版的判別函數(shù)
    :param w: 投影向量d*1
    :param S_b: 類間離散度矩陣
    :return:
    '''
    return np.dot(np.dot(np.transpose(w),S_b),w)[0][0]

plot.py

import matplotlib.pyplot as plt
from threading import Thread
from time import sleep


def draw(x,color):
    plt.hist(x, bins=50, color=color)
def show(name):
    def close(time=2):
        sleep(time)
        # plt.savefig('./img/'+name)
        plt.close()
        pass
    thread1 = Thread(target=close, args=())
    thread1.start()
    plt.show()
    pass

process_data.py

import logging
import numpy as np
import random
from main import flag

# To->process_data
#%%
if flag:
    ## ---sonar
    label=('R','M')
    file_size=(208,61)
else:
    ## ---usps
    label=('3','8')
    file_size=(9298,257)
label_dict={label[0]:1,label[1]:-1}

def save_38(data):
    import csv
    with open('usps_3&8.csv','w',newline='') as csvfile:
        writer=csv.writer(csvfile)
        writer.writerows(data)
        print('寫完了')
        exit(0)

def read_datas(file_name):
    '''
    讀取并處理文件
    :param file_name:
    :return:
    '''
    datas1,datas2=[],[]
    with open(file_name,'r') as f:
        datas=f.readlines()
    #%%
    for i in range(len(datas)):
        datas[i]=datas[i][:-1]
        datas[i]=datas[i].split(',')
        # print(i)
        datas[i][:-1]=list(map(float,datas[i][:-1]))
        # print(datas[i][-1])
        # try:
        datas[i][-1]=label_dict[datas[i][-1]]#替換成數(shù)字
        # except KeyError:
        #     continue
    # print('數(shù)據(jù)大小',np.array(datas).shape)
    # assert np.array(datas).shape==file_size
    # 可以用轉(zhuǎn)成數(shù)組處理
    for data in datas:
        # print(data[-1])
        #分別添加到兩個(gè)數(shù)據(jù)
        if data[-1]==label_dict[label[0]]:
            datas1.append(data)
        elif data[-1]==label_dict[label[1]]:
            datas2.append(data)
        else:
            # continue
            print('這個(gè)標(biāo)簽 %s 未知,請(qǐng)看一下,在第%d行' % (data[-1],datas.index(data)))
    # 可以用轉(zhuǎn)成數(shù)組處理
    #隨機(jī)一下順序
    # save_38(datas1+datas2)
    map(random.shuffle,[datas1,datas2])
    L1,L2,Lall=len(datas1),len(datas2),file_size[0]
    # assert (L1+L2)==Lall
    print('——————數(shù)據(jù)讀取完成武氓!——————')
    return ((datas1,datas2),L1,L2,Lall)
#%%
def split_datas(datas,n):
    '''
    驗(yàn)證集和訓(xùn)練集分開
    :param n: n折交叉驗(yàn)證
    :param datas: 打亂后的數(shù)據(jù),
    :return: 若n=10仇箱,第一類县恕,第二類,交叉驗(yàn)證集20*61
    '''
    data_block_len=[len(data)//n for data in datas]
    for i in range(n):
        val,cla=[],[]
        for j,data in enumerate(datas):
            val_left,val_right=data_block_len[j]*(i),data_block_len[j]*(i+1)
            val.append(np.array(data[val_left:val_right]))
            cla.append(np.array(data[:val_left]+data[val_right:]))
        yield cla,val
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剂桥,一起剝皮案震驚了整個(gè)濱河市忠烛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌权逗,老刑警劉巖美尸,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冤议,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡师坎,警方通過查閱死者的電腦和手機(jī)恕酸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胯陋,“玉大人蕊温,你說我怎么就攤上這事《羟牵” “怎么了寿弱?”我有些...
    開封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)按灶。 經(jīng)常有香客問我,道長(zhǎng)筐咧,這世上最難降的妖魔是什么鸯旁? 我笑而不...
    開封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮量蕊,結(jié)果婚禮上铺罢,老公的妹妹穿的比我還像新娘。我一直安慰自己残炮,他們只是感情好韭赘,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著势就,像睡著了一般泉瞻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上苞冯,一...
    開封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天袖牙,我揣著相機(jī)與錄音,去河邊找鬼舅锄。 笑死鞭达,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的皇忿。 我是一名探鬼主播畴蹭,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼鳍烁!你這毒婦竟也來了叨襟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬榮一對(duì)情侶失蹤老翘,失蹤者是張志新(化名)和其女友劉穎芹啥,沒想到半個(gè)月后锻离,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡墓怀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年汽纠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片傀履。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡虱朵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出钓账,到底是詐尸還是另有隱情碴犬,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布梆暮,位于F島的核電站服协,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏啦粹。R本人自食惡果不足惜偿荷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望唠椭。 院中可真熱鬧跳纳,春花似錦、人聲如沸贪嫂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽力崇。三九已至斗塘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間餐曹,已是汗流浹背逛拱。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留台猴,地道東北人朽合。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像饱狂,于是被迫代替她去往敵國(guó)和親曹步。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容