神经网络Python代码完整版及其代码解析
1、读取数据集和标签集
1 def loadDataSet():
2 data = []
3 label = []
4 fr = open('testSet.txt')
5 for line in fr.readlines(): # 循环读写,fr是一个已经打开的文件对象,readline()函数会读取文件中的一行内容
6 lineArr = line.strip().split()
7 data.append([1.0, float(lineArr[0]), float(lineArr[1])]) # 添加列表
8 label.append(int(lineArr[2])) # 添加整形
9 data = np.array(data) # 创建数组(数据集)
10 label = np.array(label)
11 return data, label
1.1、open
python提供了方便的文件读写功能,其中open是读写文件的第一步
Open的定义方式为:
file = open(path, mode = 'r', buffering = -1, encoding = None )
其中,参数:path ------ 文件路径
mode ------ 为读取模式,默认为r,即只读模式,w表示写
buffering ------ 为缓冲区,由于内存的读写速度快于外设,所以大部分情况不用设,即不大于0
encoding ------ 为编码方式
通过open
创建的文件对象,除了用于关闭文件的close
之外,有两组最常用的函数,即代表读写的read
和write
,分别用于读写,其区别如下
read \ write ------ 读写整个文件 , read(size)可读取size大小的文件
readline ------ 每次读一行
readlines \ writelines ------ 前者按行读取文件,并存入一个字符串列表; writelines将一个字符串列表的形式写入文件
1.2、 line.strip().split()
作用是对一个字符串进行处理
首先使用strip()方法删除字符串两端的空格(或其他特定字符)
然后使用split()方法将字符串按照空格进行分割,生成一个列表
strip()的用法
1、删除前面的空格
1 if __name__ == '__main__':
2 #创建一个字符串
3 s = ' abcdefd'
4 # 打印出经过strip处理之后的结果
5 print(s.strip())
2、删除首尾的空格和换行
1 if __name__ == '__main__':
2 #创建一个字符串
3 s = ' abcdefd\n'
4 # 打印出经过strip处理之后的结果
5 print(s.strip())
3、删除首尾指定的字符
1 if __name__ == '__main__':
2 #创建一个字符串
3 s = 'abcdefd'
4 # 打印出经过strip处理之后的结果
5 print(s.strip('a'))
split的用法
splitg函数通常是对字符串进行操作,操作完之后的结果,变成了一个字符串列表。
split函数按照括号内给定的字符进行分割,如果括号内是空的,也就是没有指定具体的分割内容的话,那么就默认的按照空格进行分割。
1、按照默认的方式进行划分(默认是按照空格进行分割)
1 if __name__ == '__main__':
2 #创建一个字符串
3 s = 'abc defd'
4 # 打印出经过split处理之后的结果
5 print(s.split())
2、按照指定的某一个字符进行分割,分割之后返回字符串列表,字符串列表中不包括你指定的分隔符,例如下面这个例子中,不包含d这个字母
1 if __name__ == '__main__':
2 #创建一个字符串
3 s = 'abcdefd'
4 # 打印出经过split处理之后的结果
5 print(s.split('d'))
3、也可以按照‘\n’,‘\t’进行划分
1 if __name__ == '__main__':
2 #创建一个字符串
3 s = 'abc\tdefd\t'
4 # 打印出经过split处理之后的结果
5 print(s.split('\t'))
2、NeuralNetWork类
1 class NeuralNetWork:
2 def __init__(self, input_nodes, hidden_nodes, out_nodes, lr):
3 # 设置输入个数
4 self.innodes = input_nodes
5 # 设置隐藏层节点个数
6 self.hnodes = hidden_nodes
7 # 设置输出节点个数
8 self.onodes = out_nodes
9 # 设置学习率,用于反向更新
10 self.lr = lr
11
12 # self.weight_i2h = np.ones((self.hnodes, self.innodes))
13 # self.weight_h2o = np.ones((self.onodes, self.hnodes))
14 # 随机初始化比1矩阵效果要好很多
15
16 # 权重矩阵(输入到隐藏)
17 self.weight_i2h = (numpy.random.normal(0.0, pow(self.hnodes,-0.5), (self.hnodes,self.innodes) ) )
18 # 权重矩阵(隐藏到输出)
19 self.weight_h2o = (numpy.random.normal(0.0, pow(self.onodes,-0.5), (self.onodes,self.hnodes) ) )
20 # 设置激活函数(sigmoid)
21 self.activation_function = lambda x: 1.0/(1+np.exp(-x))
22 pass
23
24 '''
25 训练方法,输入一次训练的输入和label
26 '''
27 def train(self, inputs_list, targets_list):
28 inputs = numpy.array(inputs_list, ndmin=2).T
29 target = np.array(targets_list, ndmin=2).T
30 # wx + b
31 hidden_inputs = np.dot(self.weight_i2h, inputs) # np.dot函数 主要用于矩阵的乘法运算,其中包括:向量内积、多维矩阵乘法和矩阵与向量的乘法
32 # 激活作为隐藏层的输出
33 hidden_outputs = self.activation_function(hidden_inputs)
34 # wx + b
35 o_inputs = np.dot(self.weight_h2o, hidden_outputs)
36 # 激活作为输出
37 o_outputs = self.activation_function(o_inputs) # activation_function 激活函数
38 # 损失函数
39 loss = (target - o_outputs) ** 2 * 0.5
40 # 输出误差,用于反向更新
41 error = target - o_outputs
42 # error = target - o_outputs
43 # 隐藏层误差,用于反向更新
44 hidden_error = np.dot(self.weight_h2o.T, error * o_outputs * (1 - o_outputs))
45 # 梯度
46 gradO = error * o_outputs * (1 - o_outputs)
47 # 反向更新
48 self.weight_h2o += self.lr * np.dot((error * o_outputs * (1 - o_outputs)), np.transpose(hidden_outputs))
49 gradI = hidden_error * hidden_outputs * (1 - hidden_outputs)
50 # 反向更新
51 self.weight_i2h += self.lr * np.dot((hidden_error * hidden_outputs * (1 - hidden_outputs)),
52 np.transpose(inputs))
53 return loss
2.1、numpy.random模块
numpy.random
提供了多种随机数生成函数,包括生成均匀分布、正态分布、泊松分布等各种分布的随机数
- 这个模块包含了用于生成随机数的基本函数,如
rand()
、randn()
、randint()
等。 - 例如,
rand()
生成0到1之间均匀分布的随机数,randn()
生成标准正态分布的随机数,randint()
生成整数随机数。
2.1.1、numpy.random.rand()
功能:生成均匀分布的在[0, 1)内的随机数
numpy.random.rand(d0, d1, ..., dn)
接受多个整数参数,每个参数代表生成随机数的维度。可以使用逗号分隔的整数来指定多维数组的形状。
1 import numpy as np
2
3 # 生成一个[0, 1)范围内的随机浮点数
4 rand_num = np.random.rand()
5 print(rand_num)
6
7 # 生成一个3x3的二维数组,包含[0, 1)范围内的随机浮点数
8 rand_array = np.random.rand(3, 3)
9 print(rand_array)
2.1.2、numpy.random.randn()
功能: 生成标准正态分布的随机数
numpy.random.randn(d0, d1, ..., dn)
同样接受多个整数参数,用于指定生成随机数的维度。
1 import numpy as np
2
3 # 生成一个标准正态分布的随机浮点数
4 rand_num = np.random.randn()
5 print(rand_num)
6
7 # 生成一个3x3的二维数组,包含标准正态分布的随机浮点数
8 rand_array = np.random.randn(3, 3)
9 print(rand_array)
2.1.3、numpy.random.randint()
功能: 生成整数随机数
- 参数:
numpy.random.randint(low, high, size=None, dtype=int)
其中: low
是生成的随机数的下界(包含在内)。high
是生成的随机数的上界(不包含在内)。size
是生成随机数的形状,可以是整数或元组。如果不提供,默认生成一个随机整数。dtype
是生成的随机数的数据类型,默认为整数。
1 import numpy as np
2
3 # 生成一个[0, 10)范围内的整数随机数
4 rand_int = np.random.randint(0, 10)
5 print(rand_int)
6
7 # 生成一个1x5的一维数组,包含[0, 10)范围内的整数随机数
8 rand_array = np.random.randint(0, 10, size=(1, 5))
9 print(rand_array)
2.1.4、numpy.random.normal()
功能:正态分布
使用numpy.random.normal()
函数生成。需要指定均值(loc
)和标准差(scale
)。
1 import numpy as np
2 import matplotlib.pyplot as plt
3
4 # 生成10000个均值为0、标准差为1的正态分布随机数
5 data = np.random.normal(0, 1, 10000)
6
7 # 绘制直方图
8 plt.hist(data, bins=30, density=True, alpha=0.6, color='g')
9 plt.title("Normal Distribution")
10 plt.show()
2.2、数组运算
inputs = numpy.array(inputs_list, ndmin=2).T
(1) 矩阵乘法
np.dot(A, B)
如果使用 np.mat 将二维数组准确定义为矩阵,就可以直接使用*完成矩阵乘法计算
np.mat(A) * np.mat(B)
(2) 转置
A.T
(3) 平方根
np.sqrt(a)
3、随机梯度下降(SGD)
1 def stocGradDescent(data, label):
2 m, n = np.shape(data)
3 for iter in range(200):
4 total_loss = 0
5 for i in range(m):
6 # if label[i] == 1:
7 # pass
8 # elif label[i] == 0:
9 # pass
10 # 累计每个epach的Loss观察效果
11
12 total_loss += net.train(data[i], label[i])
13 print("NO.{} Loss={}".format(iter, total_loss))
梯度下降算法每次从训练集中随机选择一个样本来进行学习。批量梯度下降算法每次都 会使用全部训练样本,因此这些计算是冗余的,因为每次都使用完全相同的样本集。而随机 梯度下降算法每次只随机选择一个样本来更新模型参数,因此每次的学习是非常快速的,并 且可以进行在线更新。随机梯度下降最大的缺点在于每次更新可能并不会按照正确的方向进 行,因此可以带来优化波动(扰动)。
参考链接:https://blog.csdn.net/qq_58146842/article/details/121280968
随机梯度下降(SGD)是一种简单但非常有效的方法,多用用于支持向量机、逻辑回归(LR)等凸损失函数下的线性分类器的学习。并且SGD已成功应用于文本分类和自然语言处理中经常遇到的大规模和稀疏机器学习问题。
SGD既可以用于分类计算,也可以用于回归计算。
SGD算法是从样本中随机抽出一组,训练后按梯度更新一次,然后再抽取一组,再更新一次,在样本量及其大的情况下,可能不用训练完所有的样本就可以获得一个损失值在可接受范围之内的模型了。(重点:每次迭代使用一组样本。)
为什么叫随机梯度下降算法呢?这里的随机是指每次迭代过程中,样本都要被随机打乱,这个也很容易理解,打乱是有效减小样本之间造成的参数更新抵消问题。
1 import cv2
2
3 import numpy as np
4
5 # 创建数据集
6 X = 2 * np.random.rand(100, 1)
7 y = 4 + 3 * X + np.random.randn(100, 1)
8 X_b = np.c_[np.ones((100, 1)), X]
9
10 # print('X的值:', X)
11 # print(y)
12 print(X_b)
13
14 # 创建超参数
15 n_epochs = 10000
16 m = 100
17 t0, t1 = 5, 500
18
19
20 # 定义一个函数来调整学习率
21 def learning_rate_schedule(t):
22 return t0 / (t + t1)
23
24
25 theta = np.random.randn(2, 1)
26 for epoch in range(n_epochs):
27 # 在双层for循环之间,每个轮次开始分批次迭代之前打乱数据索引顺序
28 arr = np.arange(len(X_b))
29 np.random.shuffle(arr)
30 X_b = X_b[arr]
31 y = y[arr]
32 for i in range(m):
33 xi = X_b[i:i + 1]
34 yi = y[i:i + 1]
35 gradients = xi.T.dot(xi.dot(theta) - yi)
36 learning_rate = learning_rate_schedule(epoch * m + i)
37 theta = theta - learning_rate * gradients
38
39 print(theta)
完整代码:
1 import numpy
2 import numpy as np
3
4 # 神经网络设计
5 # 类 : NeuralNetWork
6 # 类内初始化:__init__用以设置神经网络的参数(输入层参数、隐藏层参数、输出层参数、学习率)
7 # 类内方法:train用于训练数据,更新权重
8 # 读取数据:loadDataSet用于在txt文件中读取数据,包括输入值和label值
9 # 随机梯度下降处理:stocGradDescent用于处理训练数据的过程
10
11 # NeuralNetWork类
12 class NeuralNetWork:
13 def __init__(self, input_nodes, hidden_nodes, out_nodes, lr):
14 # 设置输入个数
15 self.innodes = input_nodes
16 # 设置隐藏层节点个数
17 self.hnodes = hidden_nodes
18 # 设置输出节点个数
19 self.onodes = out_nodes
20 # 设置学习率,用于反向更新
21 self.lr = lr
22
23 # self.weight_i2h = np.ones((self.hnodes, self.innodes))
24 # self.weight_h2o = np.ones((self.onodes, self.hnodes))
25 # 随机初始化比1矩阵效果要好很多
26
27 # 权重矩阵(输入到隐藏)
28 self.weight_i2h = (numpy.random.normal(0.0, pow(self.hnodes,-0.5), (self.hnodes,self.innodes) ) )
29 # 权重矩阵(隐藏到输出)
30 self.weight_h2o = (numpy.random.normal(0.0, pow(self.onodes,-0.5), (self.onodes,self.hnodes) ) )
31 # 设置激活函数(sigmoid)
32 self.activation_function = lambda x: 1.0/(1+np.exp(-x))
33 pass
34
35 '''
36 训练方法,输入一次训练的输入和label
37 '''
38 def train(self, inputs_list, targets_list):
39 inputs = numpy.array(inputs_list, ndmin=2).T
40 target = np.array(targets_list, ndmin=2).T
41 # wx + b
42 hidden_inputs = np.dot(self.weight_i2h, inputs)
43 # 激活作为隐藏层的输出
44 hidden_outputs = self.activation_function(hidden_inputs)
45 # wx + b
46 o_inputs = np.dot(self.weight_h2o, hidden_outputs)
47 # 激活作为输出
48 o_outputs = self.activation_function(o_inputs)
49 # 损失函数
50 loss = (target - o_outputs) ** 2 * 0.5
51 # 输出误差,用于反向更新
52 error = target - o_outputs
53 # error = target - o_outputs
54 # 隐藏层误差,用于反向更新
55 hidden_error = np.dot(self.weight_h2o.T, error * o_outputs * (1 - o_outputs))
56 # 梯度
57 gradO = error * o_outputs * (1 - o_outputs)
58 # 反向更新
59 self.weight_h2o += self.lr * np.dot((error * o_outputs * (1 - o_outputs)), np.transpose(hidden_outputs))
60 gradI = hidden_error * hidden_outputs * (1 - hidden_outputs)
61 # 反向更新
62 self.weight_i2h += self.lr * np.dot((hidden_error * hidden_outputs * (1 - hidden_outputs)),
63 np.transpose(inputs))
64 return loss
65
66
67 # 从testSet.txt中读取数据存储至样本集data和标签集label
68 def loadDataSet():
69 data = []
70 label = []
71 fr = open('testSet.txt')
72 for line in fr.readlines():
73 lineArr = line.strip().split()
74 data.append([1.0, float(lineArr[0]), float(lineArr[1])])
75 label.append(int(lineArr[2]))
76 data = np.array(data)
77 label = np.array(label)
78 return data, label
79
80
81 def stocGradDescent(data, label):
82 m, n = np.shape(data)
83 for iter in range(200):
84 total_loss = 0
85 for i in range(m):
86 # if label[i] == 1:
87 # pass
88 # elif label[i] == 0:
89 # pass
90 # 累计每个epach的Loss观察效果
91
92 total_loss += net.train(data[i], label[i])
93 print("NO.{} Loss={}".format(iter, total_loss))
94
95
96 if __name__ == '__main__':
97 input_nodes = 3
98 hidden_nodes = 3
99 output_nodes = 1
100 learning_rate = 0.1
101 net = NeuralNetWork(input_nodes, hidden_nodes, output_nodes, learning_rate)
102 data, label = loadDataSet()
103 stocGradDescent(data, label)
104 print(net.weight_i2h)
105 print(net.weight_h2o)
106 pass
可用的txt文本文件内容
1 -0.017612 14.053064 0
2 -1.395634 4.662541 1
3 -0.752157 6.538620 0
4 -1.322371 7.152853 0
5 0.423363 11.054677 0
6 0.406704 7.067335 1
7 0.667394 12.741452 0
8 -2.460150 6.866805 1
9 0.569411 9.548755 0
10 -0.026632 10.427743 0
11 0.850433 6.920334 1
12 1.347183 13.175500 0
13 1.176813 3.167020 1
14 -1.781871 9.097953 0
15 -0.566606 5.749003 1
16 0.931635 1.589505 1
17 -0.024205 6.151823 1
18 -0.036453 2.690988 1
19 -0.196949 0.444165 1
20 1.014459 5.754399 1
21 1.985298 3.230619 1
22 -1.693453 -0.557540 1
23 -0.576525 11.778922 0
24 -0.346811 -1.678730 1
25 -2.124484 2.672471 1
26 1.217916 9.597015 0
27 -0.733928 9.098687 0
28 -3.642001 -1.618087 1
29 0.315985 3.523953 1
30 1.416614 9.619232 0
31 -0.386323 3.989286 1
32 0.556921 8.294984 1
33 1.224863 11.587360 0
34 -1.347803 -2.406051 1
35 1.196604 4.951851 1
36 0.275221 9.543647 0
37 0.470575 9.332488 0
38 -1.889567 9.542662 0
39 -1.527893 12.150579 0
40 -1.185247 11.309318 0
41 -0.445678 3.297303 1
42 1.042222 6.105155 1
43 -0.618787 10.320986 0
44 1.152083 0.548467 1
45 0.828534 2.676045 1
46 -1.237728 10.549033 0
47 -0.683565 -2.166125 1
48 0.229456 5.921938 1
49 -0.959885 11.555336 0
50 0.492911 10.993324 0
51 0.184992 8.721488 0
52 -0.355715 10.325976 0
53 -0.397822 8.058397 0
54 0.824839 13.730343 0
55 1.507278 5.027866 1
56 0.099671 6.835839 1
57 -0.344008 10.717485 0
58 1.785928 7.718645 1
59 -0.918801 11.560217 0
60 -0.364009 4.747300 1
61 -0.841722 4.119083 1
62 0.490426 1.960539 1
63 -0.007194 9.075792 0
64 0.356107 12.447863 0
65 0.342578 12.281162 0
66 -0.810823 -1.466018 1
67 2.530777 6.476801 1
68 1.296683 11.607559 0
69 0.475487 12.040035 0
70 -0.783277 11.009725 0
71 0.074798 11.023650 0
72 -1.337472 0.468339 1
73 -0.102781 13.763651 0
74 -0.147324 2.874846 1
75 0.518389 9.887035 0
76 1.015399 7.571882 0
77 -1.658086 -0.027255 1
78 1.319944 2.171228 1
79 2.056216 5.019981 1
80 -0.851633 4.375691 1
81 -1.510047 6.061992 0
82 -1.076637 -3.181888 1
83 1.821096 10.283990 0
84 3.010150 8.401766 1
85 -1.099458 1.688274 1
86 -0.834872 -1.733869 1
87 -0.846637 3.849075 1
88 1.400102 12.628781 0
89 1.752842 5.468166 1
90 0.078557 0.059736 1
91 0.089392 -0.715300 1
92 1.825662 12.693808 0
93 0.197445 9.744638 0
94 0.126117 0.922311 1
95 -0.679797 1.220530 1
96 0.677983 2.556666 1
97 0.761349 10.693862 0
98 -2.168791 0.143632 1
99 1.388610 9.341997 0
100 0.317029 14.739025 0
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?