基于鸢尾花数据集实现线性判别式多分类

基于鸢尾花数据集实现线性判别式多分类

本文在自己编写梯度下降的逻辑斯蒂判别式算法的基础上,对鸢尾花数据集实现多分类。

鸢尾花数据集公包含三类数据,每条数据四个特征,从中随机选取70%的数据作为训练集,30%的数据作为测试集。
主要包含三个函数:随机生成70%测试集函数、训练函数、预测函数

随机生成70%测试集函数 randomdata

输入:无
输出:0-49之间的35个随机数

代码:
def randomdata():
    array = set()
    while(len(array) < 50*0.7):
        n = random.randint(0,49)  
        if(n in array):
            continue
        else:
            array.add(n)
    return array

训练函数 lda

输入:数据datas,标签labels,
输出:参数w
代码:

def lda(datas,labels):
    means=datas.mean(axis=0) #各个属性的均值
    stds=datas.std(axis=0) #各个属性的标准差
    N,M= datas.shape[0],datas.shape[1]+1  #N是样本数,M是参数向量的维 150 2
    K=3 #k=3是类别数
    data=np.ones((N,M))
    data[:,1:]=(datas-means)/stds #对原始数据进行标准差归一化 第一列是常数  
    w=np.zeros((K,M))  #存储参数矩阵  np.dot(x,y)  (特征数,种类数)  
    w = np.random.rand(K,M)*2-1
    w = w/100
    
    learningrate = 0.02
    labels = np.array(labels)
    
    for k in range(1000):
        sita = np.dot(w,data.T)
        y = np.exp(sita)
        for j in range(N):
            sum = 0
            for i in range(len(y)):
                sum += y[i,j]
            for i in range(len(y)):
                if(sum == 0):
                    y[i,j] = 0
                else:
                    y[i,j] = y[i,j]/sum
        y = labels.T - y
        deltaw = np.dot(y,data)
        w = w + learningrate*deltaw
        if(k % 100 == 0):
            print(w)
            
    return w

预测函数

输入:测试数据集datas,参数w,表现labels,
输出:预测准确率per
代码:

def predict(datas,w,labels):
    means=datas.mean(axis=0) #各个属性的均值
    stds=datas.std(axis=0) #各个属性的标准差
    N,M= datas.shape[0],datas.shape[1]+1  #N是样本数,M是参数向量的维 150 2

    data=np.ones((N,M))
    data[:,1:]=(datas-means)/stds #对原始数据进行标准差归一化 第一列是常数
    
    y = np.dot(w, data.T)
    
    #取y每列中最大的数所在的列,对应的花即为预测的结果,然后和labels进行比较,得到准确率
    rey = []
    for i in range(len(labels)):
        a = y[:,i]
        maxa = max(a)
        ain = -1
        for i in range(len(a)):
            if(a[i] == maxa):
                ain = i
        if(ain == 0):
            rey.append(0)
        elif(ain == 1):
            rey.append(1)
        else:
            rey.append(2)
    count = 0
    for i in range(len(rey)):
        if(rey[i] == labels[i]):
            count = count+1
    
    per = count/(len(labels))
    return per

完整代码

# -*- coding: utf-8 -*-
"""
Created on Thu Mar 26 16:47:46 2020

@author: lenovo
"""
import numpy as np  
import pandas as pd  
import matplotlib.pyplot as plt  
from matplotlib.colors import ListedColormap  
import random
import math

def main():
    path = 'iris.csv'  # 数据文件路径
    df = pd.read_csv(path)  
    y2 = df.iloc[:150, 5].values   #取得是数据的第四列 从第0列开始
    x1 = df.iloc[:150, [1, 2, 3, 4]].values  #应该取第1列和第3列 即长度信息
    #将y2转换成数字,便于后期计算
    y1 = []
    for i in range(len(y2)):
        if(y2[i] == 'setosa'):
            y1.append(0)
        elif(y2[i] == 'versicolor'):
            y1.append(1)
        else:
            y1.append(2)
    

    
    
    #划分训练数据和测试数据
    array = randomdata() #随机取 70%的数据
    y_practice = []  #训练数据标签
    y_test = []      #测试数据标签
    x_practice = []  #训练数据特征
    x_test = []      #测试数据特征
    for i in {0, 50, 100}:
        for j in range(50):
            if(j in array):
                y_practice.append(y1[j+i])
                x_practice.append(x1[j+i])
            else:
                y_test.append(y1[j+i])
                x_test.append(x1[j+i])
    x_test = np.array(x_test)
    x_practice = np.array(x_practice)
    
    yp = np.zeros((len(y_practice), 3))
    for i in range(len(y_practice)):
        yp[i,y_practice[i]] = 1
    yt = np.zeros((len(y_test), 3))
    for i in range(len(y_test)):
        yt[i,y_test[i]] = 1
    
    #通过 x_practice 和 y_practice 训练得到参数w
    w = lda(x_practice, yp)
    
    #通过 x_test 得到预测结果,与y_test比较得到准确率
    per = predict(x_test, w, y_test) #返回的是预测的概率
    print(per)
    
    
def lda(datas,labels):
    means=datas.mean(axis=0) #各个属性的均值
    stds=datas.std(axis=0) #各个属性的标准差
    N,M= datas.shape[0],datas.shape[1]+1  #N是样本数,M是参数向量的维 150 2
    K=3 #k=3是类别数
    data=np.ones((N,M))
    data[:,1:]=(datas-means)/stds #对原始数据进行标准差归一化 第一列是常数  
    w=np.zeros((K,M))  #存储参数矩阵  np.dot(x,y)  (特征数,种类数)  
    w = np.random.rand(K,M)*2-1
    w = w/100
    
    learningrate = 0.02
    labels = np.array(labels)
    
    for k in range(1000):
        sita = np.dot(w,data.T)
        y = np.exp(sita)
        for j in range(N):
            sum = 0
            for i in range(len(y)):
                sum += y[i,j]
            for i in range(len(y)):
                if(sum == 0):
                    y[i,j] = 0
                else:
                    y[i,j] = y[i,j]/sum
        y = labels.T - y
        deltaw = np.dot(y,data)
        w = w + learningrate*deltaw
        if(k % 100 == 0):
            print(w)
            
    return w

def predict(datas,w,labels):
    means=datas.mean(axis=0) #各个属性的均值
    stds=datas.std(axis=0) #各个属性的标准差
    N,M= datas.shape[0],datas.shape[1]+1  #N是样本数,M是参数向量的维 150 2

    data=np.ones((N,M))
    data[:,1:]=(datas-means)/stds #对原始数据进行标准差归一化 第一列是常数
    
    y = np.dot(w, data.T)
    
    #取y每列中最大的数所在的列,对应的花即为预测的结果,然后和labels进行比较,得到准确率
    rey = []
    for i in range(len(labels)):
        a = y[:,i]
        maxa = max(a)
        ain = -1
        for i in range(len(a)):
            if(a[i] == maxa):
                ain = i
        if(ain == 0):
            rey.append(0)
        elif(ain == 1):
            rey.append(1)
        else:
            rey.append(2)
    count = 0
    for i in range(len(rey)):
        if(rey[i] == labels[i]):
            count = count+1
    
    per = count/(len(labels))
    return per
    
    
def randomdata():
    array = set()
    while(len(array) < 50*0.7):
        n = random.randint(0,49)  
        if(n in array):
            continue
        else:
            array.add(n)
    return array



if __name__ == "__main__":
    main()
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值