《neural network and deep learning》题解——ch03 再看手写识别问题题解与源码分析

本文主要是介绍《neural network and deep learning》题解——ch03 再看手写识别问题题解与源码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://blog.csdn.net/u011239443/article/details/77649026

完整代码:https://github.com/xiaoyesoso/neural-networks-and-deep-learning/blob/master/src/network2.py

我们之前根据《neural network and deep learning》题解——ch02 反向传播讲解了ch02 Network源码分析。这篇是对ch02 Network源码分析的改进。这里我们结合《机器学习技法》学习笔记12——神经网络重新讲解下。

交叉熵代价函数

class QuadraticCost(object):@staticmethoddef fn(a, y):return 0.5 * np.linalg.norm(a - y) ** 2@staticmethoddef delta(z, a, y):return (a - y) * sigmoid_prime(z)class CrossEntropyCost(object):@staticmethoddef fn(a, y):return np.sum(np.nan_to_num(-y * np.log(a) - (1 - y) * np.log(1 - a)))@staticmethoddef delta(z, a, y):return (a - y)

这边我们把损失函数封装成两个类,静态函数 fn 返回的是损失,delta返回的是ch02 反向传播中的δ。该delta对应《机器学习技法》学习笔记12——神经网络中就是:

我们在Network中使用的就是二次代价函数,这里我们就只讲解另外的交叉熵代价函数:

对应代码:

np.sum(np.nan_to_num(-y * np.log(a) - (1 - y) * np.log(1 - a)))

接下来我们来看看关于delta的问题:

看看 network.py 中的 Network.cost_derivative ⽅法。这个⽅法是为⼆次代价函数写的。怎样修改可以⽤于交叉熵代价函数上?你能不能想到可能在交叉熵函数上遇到的问题?在 network2.py 中,我们已经去掉了Network.cost_derivative ⽅法,将其集成进了‘CrossEntropyCost.delta‘ ⽅法中。请问,这样是如何解决你已经发现的问题的?

对应《机器学习技法》学习笔记12——神经网络中,cost_derivative就是 ∂ e n ∂ x L ∂\frac{e_n}{∂x^L} xLen,有链式法则得到:
δ L = ∂ e n ∂ x L ∂ x L ∂ s L \large δ^L = \frac{∂e_n}{∂x^L}\frac{∂x^L}{∂s^L} δL=xLensLxL
network中也是的cost_derivative也是用在求δ。
而CrossEntropyCost.delta是:

return (a - y)

代码 中的 a 就是上式中的x,z 就是上式中的 s。
我们对CrossEntropyCost关于a求导,得到:
− ( y a − 1 − y 1 − a ) = − y ( 1 − a ) + a ( 1 − y ) a ( 1 − a ) = − y + a a ( 1 − a ) \large -(\frac{y}{a} - \frac{1-y}{1-a}) = \frac{-y(1-a) + a(1- y)}{a(1-a)} = \frac{-y+a}{a(1-a)} (ay1a1y)=a(1a)y(1a)+a(1y)=a(1a)y+a
所以 CrossEntropyCost 的 cost_derivative 是 − y + a a ( 1 − a ) \frac{-y+a}{a(1-a)} a(1a)y+a
由 http://blog.csdn.net/u011239443/article/details/75091283#t0 可知:
∂ a ∂ z = a ( 1 − a ) \large \frac{∂a}{∂z} = a(1-a) za=a(1a)
所以:
δ = ∂ e n ∂ a ∂ a ∂ z = − y + a a ( 1 − a ) a ( 1 − a ) = a − y \large δ = \frac{∂e_n}{∂a}\frac{∂a}{∂z} = \frac{-y+a}{a(1-a)}a(1-a) = a - y δ=aenza=a(1a)y+aa(1a)=ay

初始化

和Network基本上一样,只不过封装成了一个default_weight_initializer函数

    def __init__(self, sizes, cost=CrossEntropyCost):self.num_layers = len(sizes)self.sizes = sizesself.default_weight_initializer()self.cost = costdef default_weight_initializer(self):self.biases = [np.random.rand(y, 1) for y in self.sizes[1:]]self.weights = [np.random.rand(y, x) / np.sqrt(x) for x, y in zip(self.sizes[:-1], self.sizes[1:])]

随机梯度下降

和Network基本上一样,各个monitor是代表是否需要检测该对应的指标。

    def SGD(self, training_data, epochs, mini_batch_size, eta,lmbda=0.0,evaluation_data=None,monitor_evaluation_cost=False,monitor_evaluation_accuracy=False,monitor_training_cost=False,monitor_training_accuray=False):if evaluation_data:n_data = len(evaluation_data)n = len(training_data)evaluation_cost, evaluation_accurary = [], []training_cost, training_accuray = [], []for j in xrange(epochs):random.shuffle(training_data)mini_batches = [training_data[k:k + mini_batch_size] for k in range(0, n, mini_batch_size)]for mini_batch in mini_batches:self.update_mini_batch(mini_batch, eta, lmbda, len(training_data))print "Epoch %s training complete" %(j+1)if monitor_training_cost:cost = self.total_cost(training_data, lmbda)training_cost.append(cost)print "Cost on train: {}".format(cost)if monitor_training_accuray:acc = self.accuracy(training_data,covert=True)training_accuray.append(acc)print "Acc on train: {} / {}".format(acc,n)if monitor_evaluation_cost:cost = self.total_cost(evaluation_data, lmbda,convert=True)evaluation_cost.append(cost)print "Cost on evaluation: {}".format(cost)if monitor_evaluation_accuracy:acc = self.accuracy(evaluation_data)evaluation_accurary.append(acc)print "Acc on evaluation: {} / {}".format(acc, n_data)printreturn evaluation_cost,evaluation_accurary,training_cost,training_accuray

反向传播

    def backprop(self, x, y):nabla_b = [np.zeros(b.shape) for b in self.biases]nabla_w = [np.zeros(w.shape) for w in self.weights]activation = xactivations = [x]zs = []for b, w in zip(self.biases, self.weights):z = np.dot(w, activation) + bzs.append(z)activation = sigmoid(z)activations.append(activation)delta = (self.cost).delta(zs[-1], activations[-1], y)nabla_b[-1] = deltanabla_w[-1] = np.dot(delta, activations[-2].transpose())for l in xrange(2, self.num_layers):z = zs[-l]sp = sigmoid_prime(z)delta = np.dot(self.weights[-l + 1].transpose(), delta) * spnabla_b[-l] = deltanabla_w[-l] = np.dot(delta, activations[-l - 1].transpose())return (nabla_b, nabla_w)def update_mini_batch(self, mini_batch, eta, lmbda, n):nabla_b = [np.zeros(b.shape) for b in self.biases]nabla_w = [np.zeros(w.shape) for w in self.weights]for x, y in mini_batch:delta_nabla_b, delta_nabla_w = self.backprop(x, y)nabla_b = [nb + dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]nabla_w = [nw + dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]self.weights = [(1 - eta * (lmbda / n)) * w - (eta / len(mini_batch)) * nw for w, nw inzip(self.weights, nabla_w)]self.biases = [b - (eta / len(mini_batch)) * nb for b, nb in zip(self.biases, nabla_b)]

我们可以看到基本上和Network中一样,前面已经讲解过δ。这里的代码也可以和《机器学习技法》学习笔记12——神经网络中的公式对应:

L2规范化

主要区别是在最后两行更新的时候加入了L2规范化:

求偏导数得:

则:

L1规范化

这里引出了我们这节的另外一个问题:

更改上⾯的代码来实现 L1 规范化

求导得到:


则:

对应的代码应该写为:

  self.weights = [(1 - eta * (lmbda / n)*np.sign(w)) * w - (eta / len(mini_batch)) * nw for w, nw inzip(self.weights, nabla_w)]self.biases = [b - (eta / len(mini_batch)) * nb for b, nb in zip(self.biases, nabla_b)]

测评

有些label,我们需要对其进行二元化处理,然后使用:

def vectorized_result(j):e = np.zeros((10, 1))e[j] = 1.0return e

计算损失率

这会加入L2 规范化

    def total_cost(self, data, lmbda, convert=False):cost = 0.0for x, y in data:a = self.feedforward(x)if convert:y = vectorized_result(y)cost += self.cost.fn(a, y) / len(data)cost += 0.5 * (lmbda / len(data)) * sum(np.linalg.norm(w) ** 2 for w in self.weights)return cost

回到我们之前的L1规范化实现的问题,这里代码可改成:

cost +=  (lmbda / len(data)) * sum(np.linalg.norm(w) for w in self.weights)

计算准确率

和Network中基本上一致

    def accuracy(self,data,covert=False):if covert:results = [(np.argmax(self.feedforward(x)),np.argmax(y)) for (x,y) in data]else:results = [(np.argmax(self.feedforward(x)),y) for (x,y) in data]return sum(int(x==y) for (x,y) in results)

这里写图片描述

这篇关于《neural network and deep learning》题解——ch03 再看手写识别问题题解与源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1023050

相关文章

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

Vue项目中Element UI组件未注册的问题原因及解决方法

《Vue项目中ElementUI组件未注册的问题原因及解决方法》在Vue项目中使用ElementUI组件库时,开发者可能会遇到一些常见问题,例如组件未正确注册导致的警告或错误,本文将详细探讨这些问题... 目录引言一、问题背景1.1 错误信息分析1.2 问题原因二、解决方法2.1 全局引入 Element

关于@MapperScan和@ComponentScan的使用问题

《关于@MapperScan和@ComponentScan的使用问题》文章介绍了在使用`@MapperScan`和`@ComponentScan`时可能会遇到的包扫描冲突问题,并提供了解决方法,同时,... 目录@MapperScan和@ComponentScan的使用问题报错如下原因解决办法课外拓展总结@

MybatisGenerator文件生成不出对应文件的问题

《MybatisGenerator文件生成不出对应文件的问题》本文介绍了使用MybatisGenerator生成文件时遇到的问题及解决方法,主要步骤包括检查目标表是否存在、是否能连接到数据库、配置生成... 目录MyBATisGenerator 文件生成不出对应文件先在项目结构里引入“targetProje

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

numpy求解线性代数相关问题

《numpy求解线性代数相关问题》本文主要介绍了numpy求解线性代数相关问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 在numpy中有numpy.array类型和numpy.mat类型,前者是数组类型,后者是矩阵类型。数组

解决systemctl reload nginx重启Nginx服务报错:Job for nginx.service invalid问题

《解决systemctlreloadnginx重启Nginx服务报错:Jobfornginx.serviceinvalid问题》文章描述了通过`systemctlstatusnginx.se... 目录systemctl reload nginx重启Nginx服务报错:Job for nginx.javas