机器学习(周志华) 西瓜书 第五章课后习题5.6—— Python实现

机器学习(周志华) 西瓜书 第五章课后习题5.6—— Python实现

  • 实验题目

试设计一个BP改进算法,能通过动态调整学习率显著提升收敛速度。试编程实现该算法,并选择两个UCI数据集与标准BP算法进行实验比较。

  • 实验原理

BP构造:

Sigmoid函数:

误差逆传播:

  • 实验过程

数据集获取

选取最受欢迎的Iris数据集:

http://archive.ics.uci.edu/ml/machine-learning-databases/iris/

算法实现

构造BP神经网络模块

数据集读取

数据集预处理

主函数

  • 实验结果

case1

case2

  • 程序清单:


NeuralNetwork.py 

import math
import random
import numpy as np

class inputlayer:
    def __init__(self):
        self.output = 0

    def setOutput(self,number):
    	self.output= number

class hiddenlayer:
    def __init__(self):
        self.output = 0
        self.input = 0
        self.threshold = 0
        self.weight = []
    def setOutput(self,number):
    	self.output = number
    def setInput(self,number):
    	self.input = number
    def setThreshold(self,number):
    	self.threshold = number
    def setSingleWeight(self,number,weight):
    	self.weight[number] = weight
    def setWeight(self,weight):
    	self.weight = weight

def sigma(number):
	if number>=0:
		return 1.0/(1+np.exp(-number))
	else:
		return np.exp(number)/(1.0+np.exp(number))

def initInput(number):
	res = []
	for i in range(number):
		temp = inputlayer()
		res.append(temp)
	return res

def initHidden(number,inputSize):
	res = []
	for i in range(number):
		temp = hiddenlayer()
		weight = []
		for k in range(inputSize):
			temp1 = random.random()
			weight.append(temp1)
		temp.setWeight(weight)
		temp.setThreshold(random.random())
		res.append(temp)
	return res

def initOutput(number,hiddenSize):
	res = []
	for i in range(number):
		temp = hiddenlayer()
		weight = []
		for k in range(hiddenSize):
			temp1 = random.random()
			weight.append(temp1)
		temp.setWeight(weight)
		temp.setThreshold(random.random())
		res.append(temp)
	return res

def calcInput(hiddenLayer,inputLayers):
	total =0
	for i in range(len(inputLayers)):
		total += inputLayers[i].output*hiddenLayer.weight[i]
	return total

#用权重和阈值等跑网络
def result(inputLayer,hiddenLayer,outputLayer,xi,yi):
	result = []

	for i in range(len(xi)):
		inputLayer[i].setOutput(xi[i])
	for i in range(len(hiddenLayer)):
		hiddenLayer[i].setInput(calcInput(hiddenLayer[i],inputLayer))
		hiddenLayer[i].setOutput(sigma(hiddenLayer[i].input-hiddenLayer[i].threshold))
	for i in range(len(outputLayer)):
		outputLayer[i].setInput(calcInput(outputLayer[i],hiddenLayer))
		outputLayer[i].setOutput(sigma(outputLayer[i].input-outputLayer[i].threshold))
		result.append(outputLayer[i].output)
	return result

def calcG(yi,yk):
	g = []

	for i in range(len(yi)):
		temp = yk[i]*(1-yk[i])*(yi[i]-yk[i])
		g.append(temp)
	return g

def calcE(hiddenLayer,outputLayer,g):
	e = []
	for i in range(len(hiddenLayer)):
		temp = hiddenLayer[i].output* (1 - hiddenLayer[i].output)
		temp2 = 0
		for k in range(len(outputLayer)):
			temp2+=outputLayer[k].weight[i]*g[k]
		temp = temp2*temp
		e.append(temp)
	return e

def calc_flag(a,deta):
	if abs(a)>deta:
		return 1
	return 0

#输入层到隐层的权值,隐层的阈值,隐层到输出层的权值,输出层的阈值四种参数
def run(data_train, data_test, inputSize, hiddenSize, outputSize, deta, version):
	x, y = data_train
	test_x, test_y = data_test

	inputLayer = initInput(inputSize)
	hiddenLayer = initHidden(hiddenSize,inputSize)
	outputLayer = initOutput(outputSize,hiddenSize)

	yita = 0.005
	flag,count = 1,0 
	E , temp_e= 777,888
	while(flag):
		count+=1

		if E<= 5:
			break

		temp_e = E
		E = 0

		for xi,yi in zip(x,y):
			yk = result(inputLayer,hiddenLayer,outputLayer,xi,yi)#返回list
			g = calcG(yi,yk)
			e = calcE(hiddenLayer,outputLayer,g)
			for i in range(len(yk)):
				E+=1/2*(yk[i]-yi[i])**2

			for i in range(len(outputLayer)):
				for k in range(len(hiddenLayer)):
					temp  = yita*g[i]*hiddenLayer[k].output
					outputLayer[i].weight[k] +=temp
				temp2 = -1*yita*g[i]

				outputLayer[i].threshold+=temp2
			for h in range(len(hiddenLayer)):
				for i in range(len(inputLayer)):
					temp = yita*e[h]*xi[i]
					hiddenLayer[h].weight[i]+=temp
				temp2 = -1*yita*e[h]
				hiddenLayer[h].threshold+=temp2
				
		if abs(temp_e - E)>0.01 and version==1 and yita<0.020:
			yita*=1.1
		elif abs(temp_e - E) <0.05 and version==1 and yita>0.001:
			yita/=1.1

	right = 0
	size = outputSize
	for xi,yi in zip(test_x,test_y):
		yk = result(inputLayer,hiddenLayer,outputLayer,xi,yi)
		if list(yk).index(max(list(yk))) == list(yi).index(max(list(yi))):
			right+=1

	print('Accuracy:', str(right/test_x.shape[0])+'%')
	print('loop number:', str(count), '\n')

main.py

import NeuralNetwork
import numpy as np
import pandas as pd

D_keys = {'Iris-setosa': ['Iris-setosa','Iris-versicolor','Iris-virginica'] }
names = ['sepal length', 'sepal width', 'petal length', 'petal width', 'Iris-setosa']

def loadData(filename):
	dataSet = pd.read_csv(filename, names=names)
	return dataSet

def processData(dataSet):
	for key, value in D_keys.items():
		dataSet[key].replace(value, list(range(len(value))), inplace=True)
	dataSet['Iris-versicolor'] = 0
	dataSet['Iris-virginica'] = 0

	for i in range(dataSet.shape[0]):
		dataSet.iloc[i,6] = 1 if dataSet.iloc[i,4] == 2 else 0
		dataSet.iloc[i,5] = 1 if dataSet.iloc[i,4] == 1 else 0
		dataSet.iloc[i,4] = 1 if dataSet.iloc[i,4] == 0 else 0

	index_train = list(range(35)) + list(range(50,85)) + list(range(100,135))

	data_train = dataSet.iloc[index_train]
	data_test = dataSet.drop(index_train)

	train_x = np.array(data_train[['sepal length', 'sepal width', 'petal length', 'petal width']])
	train_y = np.array(data_train[['Iris-setosa','Iris-versicolor','Iris-virginica'] ])
	
	test_x = np.array(data_test[['sepal length', 'sepal width', 'petal length', 'petal width']])
	test_y = np.array(data_test[['Iris-setosa','Iris-versicolor','Iris-virginica']])

	return (train_x, train_y), (test_x, test_y)




if __name__ == '__main__':
	# 读取数据
	filename = '../UCI/iris/iris.data'
	dataSet = loadData(filename)
	
	data_train, data_test = processData(dataSet)

	
	print('Standard BP:')
	NeuralNetwork.run(data_train, data_test, 4, 4, 3, 0.055, 0)

	print('Dynamic BP:')
	NeuralNetwork.run(data_train, data_test, 4, 4, 3, 0.03, 1)

猜你喜欢

转载自blog.csdn.net/weixin_37922777/article/details/89183808
今日推荐