基于Python实现DNNBP神经网络对不同圆的分类算法

简介: 基于Python实现DNNBP神经网络对不同圆的分类算法

classification_BPNeuralNetwork


本文介绍了通过 Python 实现 BP 神经网络分类算法,对不同半径的圆进行多分类(3 分类),特征即为圆的半径。 输入层 12 节点,一个 6 节点的隐藏层,输出层 3 个节点。

1.目标


通过 BP 算法实现对不同半径的圆的分类。

2.开发环境


IDE:PyCharm 2018.3.3(Community Edition) Python 及相关库的版本号如下图所示:


70ab45a5d54d7f200700e9c0c430c337.png


3.准备数据


目的: 生成 3 类圆在第一象限内的坐标(圆心都是原点) 第 1 类:半径范围为 1~10,分类标识为‘0’ 第 2 类:半径范围为 10~20,分类标识为‘1’ 第 3 类:半径范围为 20~30,分类标识为‘2’


代码如下:data_generate.py

importnumpyasnpimportmathimportrandomimportcsv# 只生成第一象限内的坐标即可。每个圆生成12个坐标(x,y),相当于12个特征维度defgenerate_circle(lower,upper):# 圆在第一象限内的坐标data_ur=np.zeros(shape=(12,2))# 在上下限范围内,随机产生一个值作为半径radius=random.randint(int(lower),int(upper))# 在0~90度内,每隔7.5度取一次坐标,正好取12次angles=np.arange(0,0.5*np.pi,1/24*np.pi)foriinrange(12):temp_ur=np.zeros(2)x=round(radius*math.cos(angles[i]),2)y=round(radius*math.sin(angles[i]),2)temp_ur[0]=xtemp_ur[1]=ydata_ur[i]=temp_urreturndata_ur,label# 将坐标保存到CSV文件中defsave2csv(data,batch,label):out=open("D:\\circles.csv",'a',newline='')csv_write=csv.writer(out,dialect='excel')length=int(data.size/2)foriinrange(length):string=str(data[i][0])+','+str(data[i][1])+','+str(batch)+','+str(label)temp=string.split(',')csv_write.writerow(temp)out.close()if__name__=="__main__":'''
        生成3类圆,标签(label)分别为:0、1、2
        第1类圆的半径下限为1,上限为10
        第2类圆的半径下限为10,上限为20
        第3类圆的半径下限为20,上限为30
        圆心都为原点
    '''lower=[1,10,20]# 半径随机值的下限upper=[10,20,30]# 半径随机值的上限label=['0','1','2']# 种类的标签foriinrange(len(label)):# 每类数据生成50组forjinrange(50):data,label=generate_circle(lower[i],upper[i])batch=50*i+j+1# 数据的批次,用来区分每个坐标是属于哪个圆的save2csv(data,batch,label[i])



共 3 类圆,每类生成 50 个圆,每个圆有 12 个坐标,因此在输出文件 D:\circles.csv 中总共有 3×50×12=1800 行数据:



52fee2b619df13b0e58ae41cfcb85de9.png


通过生成的坐标绘制散点图如下:

6923a2192f0fc46cf83e173a9bfceb6b.png


图中蓝色的点是 label 为 0 的圆,绿色的点是 label 为 1 的圆,红色的点是 label 为 2 的圆。


4.处理数据


目标: 根据第 3 步获得的坐标,计算每个圆的半径(勾股定理)作为神经网络的输入。

代码如下:data_process.py


importcsvimportmathdefprocess(file_name):# 要读取的CSV文件csv_file=csv.reader(open(file_name,encoding='utf-8'))# 要生成的CSV文件out_file=open("D:\\circles_data.csv",'a',newline='')csv_write=csv.writer(out_file,dialect='excel')# 将csv_file每一行的圆坐标取出,如果是同一批次的(同一个圆),则写入到out_file的一行中rows=[rowforrowincsv_file]current_batch='unknown'current_label='unknown'data_list=[]forrinrows:# 将无关字符都替换为空格temp_string=str(r).replace('[','').replace(']','').replace('\'','')# 将字符串以逗号分隔item=str(temp_string).split(',')# 分别取出x轴坐标、y轴坐标、批次、标签x=float(item[0])y=float(item[1])batch=item[2]label=item[3]# 如果是同一批次(同一个圆),则都放入data_list中ifcurrent_batch==batch:# 根据勾股定理计算半径distance=math.sqrt(pow(x,2)+pow(y,2))data_list.append(distance)# 如果不是同一批次(同一个圆),则在末尾加上标签后,作为一行写入输出文件else:iflen(data_list)!=0:# 这个地方需注意一下,最后的标签用3列来表示,而不是一列iflabel.strip()=='0':data_list.append(1)data_list.append(0)data_list.append(0)eliflabel.strip()=='1':data_list.append(0)data_list.append(1)data_list.append(0)else:data_list.append(0)data_list.append(0)data_list.append(1)result_string=str(data_list).replace('[','').replace(']','').replace('\'','').strip()csv_write.writerow(result_string.split(','))# 清空data_list,继续写入下一个批次data_list.clear()distance=math.sqrt(pow(x,2)+pow(y,2))data_list.append(distance)current_batch=batchcurrent_label=label# 确保最后一个批次的数据能写入ifcurrent_label.strip()=='0':data_list.append(1)data_list.append(0)data_list.append(0)elifcurrent_label.strip()=='1':data_list.append(0)data_list.append(1)data_list.append(0)else:data_list.append(0)data_list.append(0)data_list.append(1)result_string=str(data_list).replace('[','').replace(']','').replace('\'','').strip()csv_write.writerow(result_string.split(','))# 关闭输出文件out_file.close()if__name__=="__main__":process('D:\\circles.csv')

需要注意的是,生成的 CSV 文件共有 15 列,前 12 列为坐标对应的半径值,最后三列组合起来表示分类(label):

afa149869d93973411f3bb1289756907.png


(1,0,0)表示类型为“0”的圆,(0,1,0)表示类型为“1”的圆,(0,0,1)表示类型为“2”的圆,这样做的目的是为了下一步使用神经网络时处理起来方便。


5.构建 BP 神经网络


上一步处理好的数据可以作为训练数据,命名为:circles_data_training.csv 重复第 3 步和第 4 步,可以生成另一批数据作为测试数据,命名为:circles_data_test.csv 当然,也可以手动划分出训练数据和测试数据。 训练数据和测试数据在输入时,做了矩阵的转置,将列转置为行。


代码如下:data_analysis_bpnn.py

importpandasaspdimportnumpyasnpimportdatetimefromsklearn.utilsimportshuffle# 1.初始化参数definitialize_parameters(n_x,n_h,n_y):np.random.seed(2)# 权重和偏置矩阵w1=np.random.randn(n_h,n_x)*0.01b1=np.zeros(shape=(n_h,1))w2=np.random.randn(n_y,n_h)*0.01b2=np.zeros(shape=(n_y,1))# 通过字典存储参数parameters={'w1':w1,'b1':b1,'w2':w2,'b2':b2}returnparameters# 2.前向传播defforward_propagation(X,parameters):w1=parameters['w1']b1=parameters['b1']w2=parameters['w2']b2=parameters['b2']# 通过前向传播来计算a2z1=np.dot(w1,X)+b1# 这个地方需注意矩阵加法:虽然(w1*X)和b1的维度不同,但可以相加a1=np.tanh(z1)# 使用tanh作为第一层的激活函数z2=np.dot(w2,a1)+b2a2=1/(1+np.exp(-z2))# 使用sigmoid作为第二层的激活函数# 通过字典存储参数cache={'z1':z1,'a1':a1,'z2':z2,'a2':a2}returna2,cache# 3.计算代价函数defcompute_cost(a2,Y,parameters):m=Y.shape[1]# Y的列数即为总的样本数# 采用交叉熵(cross-entropy)作为代价函数logprobs=np.multiply(np.log(a2),Y)+np.multiply((1-Y),np.log(1-a2))cost=-np.sum(logprobs)/mreturncost# 4.反向传播(计算代价函数的导数)defbackward_propagation(parameters,cache,X,Y):m=Y.shape[1]w2=parameters['w2']a1=cache['a1']a2=cache['a2']# 反向传播,计算dw1、db1、dw2、db2dz2=a2-Ydw2=(1/m)*np.dot(dz2,a1.T)db2=(1/m)*np.sum(dz2,axis=1,keepdims=True)dz1=np.multiply(np.dot(w2.T,dz2),1-np.power(a1,2))dw1=(1/m)*np.dot(dz1,X.T)db1=(1/m)*np.sum(dz1,axis=1,keepdims=True)grads={'dw1':dw1,'db1':db1,'dw2':dw2,'db2':db2}returngrads# 5.更新参数defupdate_parameters(parameters,grads,learning_rate=0.0075):w1=parameters['w1']b1=parameters['b1']w2=parameters['w2']b2=parameters['b2']dw1=grads['dw1']db1=grads['db1']dw2=grads['dw2']db2=grads['db2']# 更新参数w1=w1-dw1*learning_rateb1=b1-db1*learning_ratew2=w2-dw2*learning_rateb2=b2-db2*learning_rateparameters={'w1':w1,'b1':b1,'w2':w2,'b2':b2}returnparameters# 建立神经网络defnn_model(X,Y,n_h,n_input,n_output,num_iterations=10000,print_cost=False):np.random.seed(3)n_x=n_input# 输入层节点数n_y=n_output# 输出层节点数# 1.初始化参数parameters=initialize_parameters(n_x,n_h,n_y)# 梯度下降循环foriinrange(0,num_iterations):# 2.前向传播a2,cache=forward_propagation(X,parameters)# 3.计算代价函数cost=compute_cost(a2,Y,parameters)# 4.反向传播grads=backward_propagation(parameters,cache,X,Y)# 5.更新参数parameters=update_parameters(parameters,grads)# 每1000次迭代,输出一次代价函数ifprint_costandi%1000==0:print('迭代第%i次,代价函数为:%f'%(i,cost))returnparameters# 对模型进行测试defpredict(parameters,x_test,y_test):w1=parameters['w1']b1=parameters['b1']w2=parameters['w2']b2=parameters['b2']z1=np.dot(w1,x_test)+b1a1=np.tanh(z1)z2=np.dot(w2,a1)+b2a2=1/(1+np.exp(-z2))# 结果的维度n_rows=y_test.shape[0]n_cols=y_test.shape[1]# 预测值结果存储output=np.empty(shape=(n_rows,n_cols),dtype=int)# 取出每条测试数据的预测结果foriinrange(n_cols):# 将每条测试数据的预测结果(概率)存为一个行向量temp=np.zeros(shape=n_rows)forjinrange(n_rows):temp[j]=a2[j][i]# 将每条结果(概率)从小到大排序,并获得相应下标sorted_dist=np.argsort(temp)length=len(sorted_dist)# 将概率最大的置为1,其它置为0forkinrange(length):ifk==sorted_dist[length-1]:output[k][i]=1else:output[k][i]=0print('预测结果:')print(output)print('真实结果:')print(y_test)count=0forkinrange(0,n_cols):ifoutput[0][k]==y_test[0][k]andoutput[1][k]==y_test[1][k]andoutput[2][k]==y_test[2][k]:count=count+1acc=count/int(y_test.shape[1])*100print('准确率:%.2f%%'%acc)if__name__=="__main__":# 读取数据data_set=pd.read_csv('D:\\circles_data_training.csv',header=None)data_set=shuffle(data_set)# 打乱数据的输入顺序# 取出“特征”和“标签”,并做了转置,将列转置为行X=data_set.ix[:,0:11].values.T# 前12列是特征Y=data_set.ix[:,12:14].values.T# 后3列是标签Y=Y.astype('uint8')# 开始训练start_time=datetime.datetime.now()# 输入12个节点,隐层6个节点,输出3个节点,迭代10000次parameters=nn_model(X,Y,n_h=6,n_input=12,n_output=3,num_iterations=10000,print_cost=True)end_time=datetime.datetime.now()print("用时:"+str((end_time-start_time).seconds)+'s'+str(round((end_time-start_time).microseconds/1000))+'ms')# 对模型进行测试data_test=pd.read_csv('D:\\circles_data_test.csv',header=None)x_test=data_test.ix[:,0:11].values.Ty_test=data_test.ix[:,12:14].values.Ty_test=y_test.astype('uint8')predict(parameters,x_test,y_test)

上述代码可以参考这篇文章:纯 Python 实现鸢尾属植物数据集神经网络模型。


代码中需要注意的几个关键参数:


  1. learning_rate=0.0075,学习率(可调)
  2. n_h=6,隐藏层节点数(可调)
  3. n_input=12,输入层节点数
  4. n_output=3,输出层节点数
  5. num_iterations=10000,迭代次数(可调)



另外,对于 predict(parameters, x_test, y_test) 函数需要说明一下: a2 矩阵是最终的预测结果,但是是以概率的形式表示的(可以打印看一下)。通过比较 3 个类的概率,选出概率最大的那个置为 1,其它两个置为 0,形成 output 矩阵。


运行结果:

cca70180a694dd4a449b58ac3a31efcc.png


上图中第一红框表示神经网络预测出的分类结果,第二个红框表示测试集中真实的分类((1,0,0)表示这个圆属于类型“0”)。

每次运行时,正确率可能不一样,最高能达到 100%。通过调整刚才提到的关键参数中的学习率、隐藏层节点数、迭代次数可以提高正确率。


总结


神经网络的输入为 12 个半径值,输出结果为一个 3 维向量,其中置 1 的位就是对应的分类。   在实际应用中,12 个半径值对应 12 个特征,3 维向量表示能分 3 类。只要根据实际应用的需要修改特征数和分类数即可将上述程序应用于不同分类场景。


以上就是利用 BP 神经网络实现多特征多分类的全部过程。

相关文章
|
12天前
|
数据采集 缓存 定位技术
网络延迟对Python爬虫速度的影响分析
网络延迟对Python爬虫速度的影响分析
|
13天前
|
Python
Python中的异步编程:使用asyncio和aiohttp实现高效网络请求
【10月更文挑战第34天】在Python的世界里,异步编程是提高效率的利器。本文将带你了解如何使用asyncio和aiohttp库来编写高效的网络请求代码。我们将通过一个简单的示例来展示如何利用这些工具来并发地处理多个网络请求,从而提高程序的整体性能。准备好让你的Python代码飞起来吧!
35 2
|
20天前
|
数据采集 存储 JSON
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第27天】本文介绍了Python网络爬虫Scrapy框架的实战应用与技巧。首先讲解了如何创建Scrapy项目、定义爬虫、处理JSON响应、设置User-Agent和代理,以及存储爬取的数据。通过具体示例,帮助读者掌握Scrapy的核心功能和使用方法,提升数据采集效率。
63 6
|
9天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
37 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
9天前
|
机器学习/深度学习 人工智能 算法
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
手写数字识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Flask框架,开发网页端操作平台,实现用户上传一张图片识别其名称。
29 0
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
|
9天前
|
机器学习/深度学习 人工智能 算法
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
蔬菜识别系统,本系统使用Python作为主要编程语言,通过收集了8种常见的蔬菜图像数据集('土豆', '大白菜', '大葱', '莲藕', '菠菜', '西红柿', '韭菜', '黄瓜'),然后基于TensorFlow搭建卷积神经网络算法模型,通过多轮迭代训练最后得到一个识别精度较高的模型文件。在使用Django开发web网页端操作界面,实现用户上传一张蔬菜图片识别其名称。
47 0
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
|
13天前
|
机器学习/深度学习 TensorFlow 算法框架/工具
利用Python和TensorFlow构建简单神经网络进行图像分类
利用Python和TensorFlow构建简单神经网络进行图像分类
39 3
|
13天前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
30 2
|
18天前
|
数据采集 存储 XML
Python实现网络爬虫自动化:从基础到实践
本文将介绍如何使用Python编写网络爬虫,从最基础的请求与解析,到自动化爬取并处理复杂数据。我们将通过实例展示如何抓取网页内容、解析数据、处理图片文件等常用爬虫任务。
109 1
|
21天前
|
数据采集 前端开发 中间件
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第26天】Python是一种强大的编程语言,在数据抓取和网络爬虫领域应用广泛。Scrapy作为高效灵活的爬虫框架,为开发者提供了强大的工具集。本文通过实战案例,详细解析Scrapy框架的应用与技巧,并附上示例代码。文章介绍了Scrapy的基本概念、创建项目、编写简单爬虫、高级特性和技巧等内容。
47 4

热门文章

最新文章

下一篇
无影云桌面