热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从零开始训练神经网络【个人学习笔记】[2/2]

任务目标经过上次从零开始训练神经网络—Keras【学习笔记】[12]后,这次我们不借助Keras,自己使用代码编写神经网络,以实现输入一张
任务目标

  经过上次从零开始训练神经网络—Keras【学习笔记】[1/2] 后,这次我们不借助Keras,自己使用代码编写神经网络,以实现输入一张手写数字图片后,网络输出该图片对应的数字的目的

基本要求

  我们的代码要导出三个接口,分别完成以下功能:

  1. 初始化initialisation,设置输入层,中间层,和输出层的节点数。
  2. 训练train:根据训练数据不断的更新权重值
  3. 查询query,把新的数据输入给神经网络,网络计算后输出答案。(推理)

设计Network并编写代码:

下文将采用《Python Crash Course》2nd edition.,即蟒蛇书的代码扩充书写方式来展示逐步扩充我们的神经网络代码过程:


一、建立一个类(class):

class NeuralNetWork:
"""一个全链接神经网络"""def __init__(self):"""初始化网络,设置输入层,中间层,和输出层节点数"""passdef train(self):"""根据输入的训练数据更新节点链路权重"""passdef query(self):"""根据输入数据计算并输出答案"""pass

二、完善初始化initialisation部分


2.1 补充class的属性

  由于神经网络需要设定各层的节点数,以及学习率等“超参数”,来决定网络的结构、大小等性质。而这些超参数就可以在class的属性中初始化。

class NeuralNetWork:
"""一个全链接神经网络"""def __init__(self, input_nodes, hidde_nnodes, output_nodes, learning_rate):"""初始化网络,设置输入层,中间层,和输出层节点数:param input_nodes: 输入层节点数:param hidden_nodes: 中间层(隐藏层)节点数:param output_nodes: 输出层节点数:param learning_rate: 学习率"""self.inodes = input_nodesself.hnodes = hidden_nodesself.onodes = output_nodesself.lr = learning_ratepass--snip--

2.1.1 验证代码可用性

  练习初始化一个输入层,中间层和输出层都有3个节点的3层神经网络。

input_nodes = 3
hidden_nodes = 3
output_nodes = 3
learning_rate = 0.3n = NeuralNetWork(input_nodes, hidden_nodes, output_nodes, learning_rate)

out:
验证结果


2.2 初始化权重属性

  由于前层输入进行层间传递到后层某个节点须服从wx+b形式,因此我们需要构造初始化的全中矩阵。
  具体地,权重矩阵的形状应当遵守:

  • 权重矩阵的列数 == 前层输入的个数(节点数)
  • 权重矩阵的行数 == 后层接受的节点数

这一点不熟悉的,可以参考我之前的博客:练习推导一个最简单的BP神经网络训练过程【个人作业/数学推导】

  由于权重不一定都是正的,它完全可以是负数,因此我们在初始化时,把所有权重初始化为-0.5到0.5之间。

class NeuralNetWork:
"""一个全链接神经网络"""def __init__(self, input_nodes, hidde_nnodes, output_nodes, learning_rate):"""初始化网络,设置输入层,中间层,和输出层节点数:param input_nodes: 输入层节点数:param hidden_nodes: 中间层(隐藏层)节点数:param output_nodes: 输出层节点数:param learning_rate: 学习率"""self.inodes = input_nodesself.hnodes = hidden_nodesself.onodes = output_nodesself.lr = learning_rate"""构造层间权重矩阵。根据矩阵乘法。构造的权重矩阵的行数由后层节点数决定,列数由前层节点数决定。"""self.wih = numpy.random.rand(self.hnodes, self.inodes) - 0.5# wih矩阵是一个(隐藏层节点数, 输入层节点数),各元素取值[-0.5, 0.5]的矩阵,符合要求。下同。self.who = numpy.random.rand(self.onodes, self.hnodes) - 0.5pass--snip--

三、query函数的实现


3.1 层间传递算法编写

class NeuralNetWork:
"""一个全链接神经网络"""--snip--def query(self, inputs):"""根据输入数据计算并输出答案:param inputs: 暂时理解为输入层的输入数据矩阵"""hidden_inputs = numpy.dot(self.wih, inputs)# hidden_inputs是一个一维向量,每个元素对应着中间层某个节点从输入层神经元传过来后的信号量总和。pass

3.2 层内激活算法编写

  前文提到前层输入进行层间传递到后层某个节点须服从wx+b形式。那么完成这一传递任务的就可以交给query()查询函数。
  然而query()查询函数的任务不应该仅仅包括层间传递,还包括层内每个节点执行的激活函数运算,转化为该层的输出(或者是最终结果,或者是下一层的输入)。
  sigmod激活函数在Python中可以直接调用,我们要做的就是准备好参数。我们可以先把这个函数在初始化函数中设定好。

class NeuralNetWork:
"""一个全链接神经网络"""def __init__(self, input_nodes, hidde_nnodes, output_nodes, learning_rate):"""初始化网络,设置输入层,中间层,和输出层节点数:param input_nodes: 输入层节点数:param hidden_nodes: 中间层(隐藏层)节点数:param output_nodes: 输出层节点数:param learning_rate: 学习率"""self.inodes = input_nodesself.hnodes = hidden_nodesself.onodes = output_nodesself.lr = learning_rate"""构造层间权重矩阵。根据矩阵乘法。构造的权重矩阵的行数由后层节点数决定,列数由前层节点数决定。"""self.wih = numpy.random.rand(self.hnodes, self.inodes) - 0.5# wih矩阵是一个(隐藏层节点数, 输入层节点数),各元素取值[-0.5, 0.5]的矩阵,符合要求。下同。self.who = numpy.random.rand(self.onodes, self.hnodes) - 0.5'''scipy.special.expit对应的是sigmod函数.使用Python保留关键字lambda构造匿名函数lambda x: scipy.special.expit(x)可以直接得到激活函数计算后的返回值。'''self.activation_function = lambda x: scipy.special.expit(x)--snip--def query(self, inputs):"""根据输入数据计算并输出答案:param inputs: 输入层的输入数据矩阵"""hidden_inputs = numpy.dot(self.wih, inputs)# hidden_inputs是一个一维向量,每个元素对应着中间层某个节点从输入层神经元传过来后的信号量总和。pass

3.3 继续完成query函数编写

  至此我们就可以分别调用激活函数计算中间层的输出信号,以及输出层经过激活函数后形成的输出信号。

class NeuralNetWork:
"""一个全链接神经网络"""--snip--def query(self, inputs):"""层间数据传递的计算,层内执行激活函数计算:param inputs: 输入层的输入数据矩阵:return: 神经网络一次正向传递的最终输出"""# 数据由输入层向中间层(隐藏层)进行层间传递,按照加权求和的规则计算hidden_inputs = np.dot(self.wih, inputs)# 数据在中间层(隐藏层)的接收端向输出端进行层内传递,经过激活函数后形成的输出数据矩阵hidden_outputs = self.activation_function(hidden_inputs)# 数据由中间层(隐藏层)向输出层进行层间传递,按照加权求和的规则计算final_inputs = np.dot(self.who, hidden_outputs)# 数据在输出层的接收端向输出端进行层内传递,经过激活函数后形成的最终的输出数据矩阵final_outputs = self.activation_function(final_inputs)print(final_outputs)return final_outputs

  到目前为止,我们不妨使用一组数据来测试一下神经网络框架的代码:

input_n = 3
hidden_n = 3
output_n = 3
learning_r = 0.3
n = NeuralNetWork(input_n, hidden_n, output_n, learning_r)
n.query([1.0, 0.5, -1.5])

out:
测试结果


四、训练train过程的实现

  完成以上代码后,神经网络的大体框架就完成了,我们留下最重要的train函数,也就是通过训练样本训练链路权重的流程到下一步实现。
  训练过程分两步:

  1. 计算输入训练数据,给出网络的计算结果,这点跟query()功能很像。(这正是我们完成query函数代码的原因)
  2. 将计算结果与正确结果相比对,获取误差,采用误差反向传播法更新网络里的每条链路权重。

4.1 正向传播过程

  我们先用代码完成第一步:

class NeuralNetWork:
"""一个全链接神经网络"""--snip--def train(self, inputs_list, targets_list):"""完成训练过程:param inputs_list: 输入的训练数据:param targets_list: 训练数据对应的正确结果"""inputs = np.array(inputs_list, ndmin=2).Ttargets = np.array(targets_list, ndmin=2).T# 数据由输入层向中间层(隐藏层)进行层间传递,按照加权求和的规则计算hidden_inputs = np.dot(self.wih, inputs)# 数据在中间层(隐藏层)的接收端向输出端进行层内传递,经过激活函数后形成的输出数据矩阵hidden_outputs = self.activation_function(hidden_inputs)# 数据由中间层(隐藏层)向输出层进行层间传递,按照加权求和的规则计算final_inputs = np.dot(self.who, hidden_outputs)# 数据在输出层的接收端向输出端进行层内传递,经过激活函数后形成最终的输出数据矩阵final_outputs = self.activation_function(final_inputs)pass--snip--

  可以发现与query()极其相似。

4.2 反向传播过程

  这里注意,如下反向传播计算式的形式是由我们使用的损失函数为MSE函数,以及上文提到激活函数为sigmoid函数共同决定的,某些资料里省略了。

class NeuralNetWork:
"""一个全链接神经网络"""--snip--def train(self, inputs_list, targets_list):"""完成训练过程:param inputs_list: 输入的训练数据:param targets_list: 训练数据对应的正确结果"""inputs = np.array(inputs_list, ndmin=2).Ttargets = np.array(targets_list, ndmin=2).T# 数据由输入层向中间层(隐藏层)进行层间传递,按照加权求和的规则计算hidden_inputs = np.dot(self.wih, inputs)# 数据在中间层(隐藏层)的接收端向输出端进行层内传递,经过激活函数后形成的输出数据矩阵hidden_outputs = self.activation_function(hidden_inputs)# 数据由中间层(隐藏层)向输出层进行层间传递,按照加权求和的规则计算final_inputs = np.dot(self.who, hidden_outputs)# 数据在输出层的接收端向输出端进行层内传递,经过激活函数后形成最终的输出数据矩阵final_outputs = self.activation_function(final_inputs)# (↓反向传播过程)# 计算正向传播输出结果与标签的误差output_errors = targets - final_outputshidden_errors = np.dot(self.who.T, output_errors * final_outputs * (1 - final_outputs))# 按照链式求导法则求出损失函数MSE对各个权重w的偏导数,依据梯度下降法更新各权重self.who += self.lr * np.dot((output_errors * final_outputs * (1 - final_outputs)), np.transpose(hidden_outputs))self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1 - hidden_outputs)), np.transpose(inputs)) # self.wih更新算式中,np.dot()的第一个参数表达式应用了“数组乘法”pass--snip--

  想要看懂上述权重更新代码的提示:

  1. 要在数学上实现反向传播过程的推导,得到损失函数MSE对各权重wi的偏导数表达式;
  2. 根据”输入→中间层“和”中间层→输出层“,将偏导数分为两组∂MSE/∂[w1,w2,w3,w4]和∂MSE/∂[w5,w6,w7,w8];
  3. 将偏导数的多项式表达式形式,转换成矩阵乘法表达式形式;
  4. 转换时尽量做到矩阵形式中每一项的样子与数据在变量中存储形式一致,这样更容易理解和编写代码。
  5. 将某些步骤中“对角阵与列向量乘法”变成了更加容易用代码实现的“数组乘法”
  6. 权重更新语句是“+=”,是因为偏导数和梯度下降法均有“-”负负得正

如果上述代码和提示对你来说仍然过于“抽象”,那么请继续参考我之前写过的:练习推导一个最简单的BP神经网络训练过程【个人作业/数学推导】
其中对本文最重要结论如下图中展示的算式:
1234
5678


五、导入数据训练神经网络

  使用实际数据来训练我们的神经网络

5.1 “看”一下数据集(可选)

class NeuralNetWork:--snip--data_file = open(".../mnist_test.csv") # 各位可以使用自己的数据集,这里.csv文件中存储的是10张(28,28)的手写数字图片,每张图片和其标签数据以一维数组(长度1+28*28)形式存在.csv的某行中。
data_list = data_file.readlines()
data_file.close()
print(len(data_list))
print(data_list[0])# 把数据依靠','区分,并分别读入
all_values = data_list[0].split(',')
# 第一个值对应的是图片的标签,所以我们读取图片数据时要去掉第一个数值
image_array = np.asfarray(all_values[1:]).reshape((28, 28))
plt.imshow(image_array, cmap='Greys', interpolation='None')
plt.show()

Out:
7


5.2 初始化神经网络

  有了神经网络,我们就能利用它将输入图片和对应的正确数字之间的联系,通过训练让神经网络“学会”它。
  由于一张图片总共有28*28 = 784个数值,因此我们需要让网络的输入层具备784个输入节点。
  这里需要注意的是,中间层的节点我们选择了100个神经元,这个选择是经验值。中间层的节点数没有专门的办法去规定,其数量会根据不同的问题而变化。
  确定中间层神经元节点数最好的办法是实验,不停的选取各种数量,看看那种数量能使得网络的表现最好。

class NeuralNetWork:--snip--inputnodes = 784 # 28*28=784,是一个图片数据的像素个数
hiddennodes = 100 # 100:经验值
outputnodes = 10 # 一共10个数字,用10个节点即可输出one-hot编码对应格式的结果供判断
learningrate = 0.3
n = NeuralNetWork(inputnodes, hiddennodes, outputnodes, learningrate) # 实例化

5.3 加载训练数据集

--snip--training_data_file = open(".../mnist_test.csv", 'r') # 只读模式加载数据,注意检查文件存储路径
training_data_list = training_data_file.readlines() # 将每一行数据作为一个元素,存储在一个list中
training_data_file.close() # 关闭文件

5.4 训练神经网络

  该步骤包含了训练截止条件设定(epoch),数据的归一化处理,数据标签的one-hot编码等过程。为保证代码不过于零碎,说明解释性文字采用代码注释的形式给出。

--snip--epochs = 5 # 每个数据被遍历5次
for e in range(epochs):for record in training_data_list:all_values = record.split(',') # 把数据靠','分割,并分别读入"""接下来可以将数据“归一化”,也就是把所有数值全部转换到0.01到1.0之间。由于表示图片的二维数组中,每个数大小不超过255,由此我们只要把所有数组除以255,就能让数据全部落入到0和1之间。有些数值很小,除以255后会变为0,这样“有可能”导致链路权重更新出意想不到的问题。所以我们需要把除以255后的结果先乘以0.99,然后再加上0.01,这样所有数据就处于0.01到1之间。"""inputs = (np.asfarray(all_values[1:])) / 255.0 * 0.99 + 0.01 # 首个元素是标签,在inputs读取时要去掉。进行“数据分割”。# 设置图片与数值的对应关系,ont-hot编码targets = np.zeros(outputnodes) + 0.01 # 创建一个10个元素的数组,各元素均为0.01targets[int(all_values[0])] = 0.99 # 在数组中,将等同于数字值的索引的元素替换为0.99。假设数字7,就把索引7(第8个)数字更换为0.99n.train(inputs, targets) # 启用训练过程

  如果你觉得这个部分的功能应该在代码编写的时候作为class NeuralNetWork中train和query一样的一个方法,也可以自行改写或重写这段代码。
  悄悄话:改写好的代码我已经放在文末的附录了~

六,测试神经网络训练效果


6.1 加载测试数据

--snip--test_data_file = open(".../mnist_test.csv")
test_data_list = test_data_file.readlines()
test_data_file.close()

6.2 测试正确率

  运用测试数据,通过query()函数让神经网络做出判断,正确得1分,错误得0分。
  最后通过的分数占总次数的比值作为评估神经网络训练的指标。

--snip--scores = [] # 设定一个列表记录每次判断的得分情况,判断正确存入1,错误存入0
for record in test_data_list:all_values = record.split(',')correct_number = int(all_values[0]) # 提取标签值print("该图片对应的数字为:", correct_number)inputs = (np.asfarray(all_values[1:])) / 255.0 * 0.99 + 0.01 # 归一化outputs = n.query(inputs) # 让训练好的神经网络判断图片对应的数字并输出结果label = np.argmax(outputs) # 应用numpy.argmax()函数找到数值最大的神经元对应的编号print("网络认为图片的数字是:", label)if label == correct_number:scores.append(1)else:scores.append(0)
print(f"得分记录:\n{scores}")# 计算图片判断的成功率
scores_array = np.asarray(scores)
print(f"perfermance = {scores_array.sum() / scores_array.size * 100}%")

  运行一下,博主运行了四五次,正确率大概在80%~100%之间,如下分享部分运行日志:

某一次测试:

该图片对应的数字为: 7
神经网络判断输出结果:[0.04490563 0.1442118 0.01057779 0.03840048 0.10869915 0.10087318
0.02624607 0.50353098 0.01978388 0.3832254 ]
网络认为图片的数字是: 7

该图片对应的数字为: 2
神经网络判断输出结果:[0.03350826 0.19402964 0.8244046 0.03923834 0.10463468 0.11580433
0.0219085 0.01078036 0.03336618 0.20670527]
网络认为图片的数字是: 2

该图片对应的数字为: 1
神经网络判断输出结果:[0.05772382 0.82646153 0.08554279 0.026443 0.10922416 0.10826541
0.06526364 0.03217652 0.05343728 0.41798268]
网络认为图片的数字是: 1

该图片对应的数字为: 0
神经网络判断输出结果:[0.75354885 0.00469123 0.10610267 0.04624908 0.06654835 0.25189698
0.01219346 0.04163698 0.02263259 0.22938364]
网络认为图片的数字是: 0

该图片对应的数字为: 4
神经网络判断输出结果:[0.06560732 0.02923927 0.01173238 0.06191911 0.58371914 0.04675726
0.02078057 0.0478471 0.03739525 0.39723215]
网络认为图片的数字是: 4

该图片对应的数字为: 1
神经网络判断输出结果:[0.03902202 0.8389586 0.0657253 0.01908614 0.07016369 0.20796944
0.04493151 0.0493951 0.0317052 0.50017788]
网络认为图片的数字是: 1

该图片对应的数字为: 4
神经网络判断输出结果:[0.01736686 0.06961667 0.03573381 0.02303936 0.76090355 0.06674459
0.05125742 0.07640926 0.01028558 0.29533893]
网络认为图片的数字是: 4

该图片对应的数字为: 9
神经网络判断输出结果:[0.11019431 0.08369413 0.04207057 0.04246999 0.08058493 0.07806882
0.00777434 0.08662602 0.04694908 0.57857676]
网络认为图片的数字是: 9

该图片对应的数字为: 5
神经网络判断输出结果:[0.1498377 0.04490002 0.0911285 0.01397933 0.13341466 0.44113759
0.01476506 0.03469851 0.0448106 0.25640707]
网络认为图片的数字是: 5

该图片对应的数字为: 9
神经网络判断输出结果:[0.05914363 0.11508302 0.03964155 0.02739487 0.08430381 0.11847783
0.05053017 0.14199462 0.02186278 0.6277568 ]
网络认为图片的数字是: 9

得分记录:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
perfermance = 100.0%


另一次测试

该图片对应的数字为: 7
神经网络判断输出结果:[0.02265905 0.03422366 0.06430731 0.03609857 0.22654582 0.09591944
0.02100579 0.75224205 0.01851069 0.12818351]
网络认为图片的数字是: 7

该图片对应的数字为: 2
神经网络判断输出结果:[0.10963591 0.09466725 0.80127158 0.04624556 0.06273288 0.0108084
0.02432404 0.01778638 0.02363708 0.12300765]
网络认为图片的数字是: 2

该图片对应的数字为: 1
神经网络判断输出结果:[0.09640155 0.77838901 0.02933256 0.04210427 0.11360658 0.06766493
0.052675 0.03493176 0.03070893 0.28625836]
网络认为图片的数字是: 1

该图片对应的数字为: 0
神经网络判断输出结果:[0.7237887 0.03547681 0.07877899 0.05324199 0.17120737 0.0149062
0.02448635 0.0682549 0.0351064 0.23182087]
网络认为图片的数字是: 0

该图片对应的数字为: 4
神经网络判断输出结果:[0.05946789 0.02326259 0.05029738 0.03110391 0.3446047 0.05265512
0.05653835 0.07649995 0.06696382 0.27745743]
网络认为图片的数字是: 4

该图片对应的数字为: 1
神经网络判断输出结果:[0.06971733 0.84624108 0.03975012 0.05342429 0.09792431 0.06858301
0.03652602 0.03837132 0.04676739 0.23421643]
网络认为图片的数字是: 1

该图片对应的数字为: 4
神经网络判断输出结果:[0.06727082 0.02175992 0.09172235 0.01222416 0.7647925 0.0728403
0.04735842 0.08916765 0.03130962 0.28624597]
网络认为图片的数字是: 4

该图片对应的数字为: 9
神经网络判断输出结果:[0.08551987 0.07957313 0.10618406 0.0102303 0.07864775 0.01744719
0.00578813 0.06349602 0.04352108 0.44316604]
网络认为图片的数字是: 9

该图片对应的数字为: 5
神经网络判断输出结果:[0.1020314 0.10072958 0.05474097 0.04504972 0.09402001 0.037387
0.0326212 0.07542155 0.02800163 0.05423302]
网络认为图片的数字是: 0

该图片对应的数字为: 9
神经网络判断输出结果:[0.08643607 0.1041881 0.02615816 0.01081672 0.1368236 0.04170109
0.00848632 0.07306719 0.03210684 0.85766101]
网络认为图片的数字是: 9

得分记录:
[1, 1, 1, 1, 1, 1, 1, 1, 0, 1]
perfermance = 90.0%


七,结语

  至此一个较为完整的神经网络的编写、训练和测试过程就完成了。不依托任何成熟的框架,使用常用的numpy等库完成了对手写数字的识别工作。
  当然,我们要看到该神经网络并不是很“灵活”,例如:

  • 激活函数和损失函数也是固定在代码和计算式之中的;
  • 不能像Keras中那样增删层;
  • 权重更新算法部分是根据“输入层→中间层(一层)→输出层”结构推导的结果,二者绑定性强;
  • 没有根据损失函数的值来截止训练的功能
  • 不能图形化输出神经网络结构,需要发挥个人想象力
  • ......
  以上确实是本设计神经网络的部分缺点,但需要解释的是在编写神经网络去实现特定目的时不应当过分追求完美,上述缺点也是做权衡取舍后的结果。舍掉一些不必要的功能,在某些情况下可以保证既达到预期目的,又控制住了成本。

  不过对处于学习状态的我而言,今后应当抓住机会将这些“缺憾”补全。共勉!

Appendix:

  将训练实例化的神经网络功能集成为class中的一个method的代码分享给大家。
  注意集成后,后面实际训练的代码也要修改,这个就交给各位自行完成。

class NeuralNetWork:--snip--def network_train(self, data, epoches=5):"""完成整个训练网络的训练过程(权重更新过程)部分:param data: 训练集,包含数据和标签:param epoches: 数据被遍历次数"""for e in range(epoches):for record_ in data:all_values_ = record_.split(',') # 把数据依靠','分割,并分别读入"""接下来可以将数据“归一化”,也就是把所有数值全部转换到0.01到1.0之间。由于表示图片的二维数组中,每个数大小不超过255,由此我们只要把所有数组除以255,就能让数据全部落入到0和1之间。有些数值很小,除以255后会变为0,这样“有可能”导致链路权重更新出意想不到的问题。所以我们需要把除以255后的结果先乘以0.99,然后再加上0.01,这样所有数据就处于0.01到1之间。"""inputs_ = (np.asfarray(all_values_[1:])) / 255.0 * 0.99 + 0.01 # 首个元素是标签,在inputs读取时要去掉。进行“数据分割”# 设置图片与数值的对应关系,ont-hot编码targets_ = np.zeros(self.onodes) + 0.01 # 创建一个10个元素的数组,各元素均为0.01targets_[int(all_values_[0])] = 0.99 # 在数组中,将等同于数字值的索引的元素替换为0.99。假设数字7,就把索引7(第8个)数字更换为0.99self.train(inputs_, targets_) # 启用训练过程--snip--#TODO 实际训练部分代码修改


推荐阅读
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • Python字典推导式及循环列表生成字典方法
    本文介绍了Python中使用字典推导式和循环列表生成字典的方法,包括通过循环列表生成相应的字典,并给出了执行结果。详细讲解了代码实现过程。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文介绍了如何使用Python正则表达式匹配MATLAB的函数语法,包括多行匹配和跨行签名的处理方法。同时,作者还分享了自己遇到的问题和解决方案。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
author-avatar
多米音乐_34084632
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有