本文在自己编写梯度下降的逻辑斯蒂判别式算法的基础上,对鸢尾花数据集实现多分类。
鸢尾花数据集公包含三类数据,每条数据四个特征,从中随机选取70%的数据作为训练集,30%的数据作为测试集。
主要包含三个函数:随机生成70%测试集函数、训练函数、预测函数
输入:无
输出: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()