吴恩达深度学习第二周-二分分类,线性回归,向量化

二分分类

判断这张图片是不是猫,input一张image,output一个数,1代表是猫,0代表不是猫。

计算机中图片的表示是由像素组成的,而一个像素有red、green、blue三个参数表示。我们要将整张图片输入,即是将整张图片的数据作为一个x,那我们就将这张64*64的图片设为一个向量,那么这个向量的参数就是64*64*3=12288,我们就说这个向量的维度为n,n=12288。将x输入后,会输出一个y,y有1和0两种结果。

线性回归

给定一个x,能输出一个值y尖,我们称之为yhat,yhat表示y=1的一种可能性或者机会。比如输入一张图片,让yhat来告诉我们这是一张猫的概率有多大。在之前的视频中所说的,是一个n(x)维的向量(相当于有个n(x)个特征的特征向量)。我们用w来表示逻辑回归的参数,这也是一个n(x)维向量(因为实际上是特征权重,维度与特征向量相同),参数里面还有b,这是一个实数(表示偏差)。所以给出输入x以及参数w和b之后,我们怎样产生输出预测值yhat,一件你可以尝试却不可行的事是让yhat=w.t*x+b。

逻辑回归的代价函数(Logistic Regression Cost Function)

代价函数:为了训练逻辑回归模型的参数w参数和参数b,我们需要一个代价函数,通过训练代价函数来得到参数w和参数b。

  为了让模型学习调整参数,我们需要给定一个样本m的训练集,然后找到一个最适合的参数w和b,使得损失函数最小,即是预测值和误差值的误差平方和最小。这样才能在我们输入一个测试集时,得到我们想要得到的答案。

我在之前学习机器学习的时候写过代价函数的介绍,在下面这篇文章中。我最开始接触机器学习时我以为代价函数就是损失函数的别名,但是突然发现不是,所以我看了我之前的学习记录,也查了一下代价函数和损失函数的区别:

损失函数(Loss Function )是定义在单个样本上的,算的是一个样本的误差。

代价函数(Cost Function )是定义在整个训练集上的,是所有样本误差的平均,也就是损失函数的平均。

目标函数(Object Function)定义为:最终需要优化的函数。等于经验风险+结构风险(也就是Cost Function + 正则化项)。

关于目标函数和代价函数的区别还有一种通俗的区别:目标函数是最大化或者最小化,而代价函数是最小化

讲这个的原文链接:https://blog.csdn.net/lyl771857509/article/details/79428475

https://blog.csdn.net/weixin_41625657/article/details/94719827

我之前写过代价函数的详细计算方式,但是没有解释代价函数,时隔一个多月,之前的文章是随着学习进度每天记录的,也没有公开发表,所以有点混乱。以后会慢慢调整。

https://blog.csdn.net/weixin_41625657/article/details/95938709

 

损失函数:

损失函数又叫做误差函数(Loss function),用来衡量算法的运行情况。

损失函数只适用于像这样的单个训练样本,而代价函数是参数的总代价,所以在训练逻辑回归模型时候,我们需要找到合适的w和b,来让代价函数J 的总代价降到最低。

 

梯度下降法(Gradient Descent)

梯度下降法的详细介绍和实战代码:

https://blog.csdn.net/weixin_41625657/article/details/94752650

1、以如图的小红点的坐标来初始化参数w和b。

2、朝最陡的下坡方向走一步,不断地迭代。

3、直到走到全局最优解或者接近全局最优解的地方。

 

梯度下降法的计算:

吴恩达老师对数学中求导数和偏导数有一个说明:为什么要在代码中对偏导数用dw来表示偏导数。

Computation Graph计算图

正向传播是蓝色箭头,是从左到右的计算。下面我们看如何利用倒数进行反向计算,即红色箭头。

复合函数的求导:

逻辑回归中的梯度下降(Logistic Regression Gradient Descent)

所以梯度下降法,就是通过知道最终值反向求导,一步一步的讲最原始的数据的变化量求出,最终确定参数w,b。

m 个样本的梯度下降(Gradient Descent on m Examples)

将梯度下降法从1个逻辑回归应用到多个逻辑回归中。

这是下面各个变量名的含义:

下面我们用一个程序来表示:d后面加一个未知数表示对这个未知数求导,dw1,dw2,db的求导是从z(i)函数中所求的。

J=0;dw1=0;dw2=0;db=0;

for i = 1 to m

    z(i) = wx(i)+b;

    a(i) = sigmoid(z(i));

    J += -[y(i)log(a(i))+(1-y(i))log(1-a(i));

    dz(i) = a(i)-y(i);

    dw1 += x1(i)dz(i);

    dw2 += x2(i)dz(i);

    db += dz(i);

J/= m;

dw1/= m;

dw2/= m;

db/= m;

w=w-alpha*dw

b=b-alpha*db

 

对上面的代码不断迭代,直到找到最适合的能够使代价函数最小的w和b,可以预先设定一个迭代次数。

下面是我的另一张关于梯度下降法的说明,可以把两部分对应起来,只是那边的θ0,1,2对应这边的b和w1,w2;h(x)对应z(i)。

https://blog.csdn.net/weixin_41625657/article/details/94752650

上面的参数计算中有一个明显的缺点,即是在代码中会有两个for循环,而我们在进行深度学习模型的训练时,往往会有多个参数和大量数据,这会造成训练时间大大增加。所以能够应用你的算法且没有显式的for循环会是重要的,并且会帮助你适用于更大的数据集。所以这里有一些叫做向量化技术,它可以允许你的代码摆脱这些显式的for循环。我想在先于深度学习的时代,也就是深度学习兴起之前,向量化是很棒的。有时候可以加速你的运算,但有时候也未必。但是在深度学习时代,向量化、摆脱for循环已经变得相当重要。我们越来越多地训练非常大的数据集,所以我们要是=使代码变得非常高效。接下来学习向量化,以及如何应用向量化而连一个for循环都不使用。

向量化(Vectorization)

向量化即是将一系列数据化为向量的形式进行计算,这样能够大大节省运行时间,所以这就是python中numpy库的原因。

下面看一段代码,来发现向量化和非向量化的时间复杂度的差距:

import numpy as np #导入numpy库

a = np.array([1,2,3,4]) #创建一个数据a

print(a)

# [1 2 3 4]

import time #导入时间库

a = np.random.rand(1000000)

b = np.random.rand(1000000) #通过round随机得到两个一百万维度的数组

tic = time.time() #现在测量一下当前时间

#向量化的版本

c = np.dot(a,b)

toc = time.time()

print(“Vectorized version:” + str(1000*(toc-tic)) +”ms”) #打印一下向量化的版本的时间

​

#继续增加非向量化的版本

c = 0

tic = time.time()

for i in range(1000000):

    c += a[i]*b[i]

toc = time.time()

print(c)

print(“For loop:” + str(1000*(toc-tic)) + “ms”)#打印for循环的版本的时间

运行结果:

在两个方法中,向量化和非向量化计算了相同的值,向量化版本花费了1.5毫秒,非向量化版本的for循环花费了大约几乎500毫秒,非向量化版本多花费了300倍时间。所以在这个例子中,仅仅是向量化这么简单的代码,就会运行300倍快。这意味着如果向量化方法需要花费一分钟去运行的数据,for循环将会花费5个小时去运行。

一句话总结,以上都是再说和for循环相比,向量化可以快速得到结果。

你可能听过很多类似如下的话,“大规模的深度学习使用了GPU或者图像处理单元实现”,但是我做的所有的案例都是在jupyter notebook上面实现,这里只有CPUCPUGPU都有并行化的指令,他们有时候会叫做SIMD指令,这个代表了一个单独指令多维数据,这个的基础意义是,如果你使用了built-in函数,像np.function或者并不要求你实现循环的函数,它可以让python充分利用并行化计算,这是事实在GPUCPU上面计算,GPU更加擅长SIMD计算,但是CPU事实上也不是太差,可能没有GPU那么擅长吧。接下来,学习向量化怎么能够加速你的代码,经验法则是,无论什么时候,避免使用明确的for循环。

https://blog.csdn.net/weixin_41625657/article/details/94596272

这是关于numpy的一些语法规则,里面也有关于矩阵计算的函数之类的归纳。

向量化逻辑回归(Vectorizing Logistic Regression)

向量化如果要容易理解的话就需要知道线性代数之中矩阵的计算了,矩阵的乘法,矩阵的转置,矩阵的逆,我是本科的时候就有过线性代数的学习,再加上考研的时候考数学一,也加强了线性代数的知识,所以对于向量化的这几个视频我自己觉得没什么好写的,如果有困难可以去学习一下线性代数中矩阵的运算规则。

向量化 logistic 回归的梯度输出(Vectorizing Logistic Regression's Gradient)

 

现在我们利用前五个公式完成了前向和后向传播,也实现了对所有训练样本进行预测和求导,再利用后两个公式,梯度下降更新参数。我们的目的是不使用for循环,所以我们就通过一次迭代实现一次梯度下降,但如果你希望多次迭代进行梯度下降,那么仍然需要for循环,放在最外层。不过我们还是觉得一次迭代就进行一次梯度下降,避免使用任何循环比较舒服一些。

最后,我们得到了一个高度向量化的、非常高效的逻辑回归的梯度下降算法。

Python 中的广播(Broadcasting in Python)

这是一个不同食物(每100g)中不同营养成分的卡路里含量表格,表格为3行4列,列表示不同的食物种类,从左至右依次为苹果,牛肉,鸡蛋,土豆。行表示不同的营养成分,从上到下依次为碳水化合物,蛋白质,脂肪。

那么,我们现在想要计算不同食物中不同营养成分中的卡路里百分比。

现在计算苹果中的碳水化合物卡路里百分比含量,首先计算苹果(100g)中三种营养成分卡路里总和56+1.2+1.8 = 59,然后用56/59 = 94.9%算出结果。

可以看出苹果中的卡路里大部分来自于碳水化合物,而牛肉则不同。

对于其他食物,计算方法类似。首先,按列求和,计算每种食物中(100g)三种营养成分总和,然后分别用不用营养成分的卡路里数量除以总和,计算百分比。

我们不用for循环来做这个程序,用向量化。

import numpy as np

A = np.array([[56.0,0.0,4.4,68.0],
              [1.2,104.0,52.0,8.0],
              [1.8,135.0,99.0,0.9]])
print(A)

cal = A.sum(axis=0) #0是按列,1是按行
print(cal)

percentage = 100*A/cal.reshape(1,4)
print(cal.reshape(1,4))
print(percentage)

 cal.reshape(1,4)是重定义一个矩阵的大小,因为矩阵的计算对矩阵的大小是很严格的,所以如果不确定矩阵的大小时可以重定义矩阵的大小,以确保矩阵是我们想要的大小。矩阵的reshape()函数时间复杂度是O(1),所以几乎不算计算时间,在我们不确定的时候,我们都可以加上reshape确保程序的正确运行。

向量的广播是可以运用到行,也可以运用到列。如上,是两个矩阵大小不同,但是要做相应的运算时在行和列上的广播情况,都是运用reshape这个核心。

首先是numpy广播机制

如果两个数组的后缘维度的轴长度相符或其中一方的轴长度为1,则认为它们是广播兼容的。广播会在缺失维度和轴长度为1的维度上进行。

 

如果还不太明白,或者想知道更多东西,可以去看numpy的相关文件。

关于 python _ numpy 向量的说明(A note on python or numpy vectors)

为了演示Python-numpy的一个容易被忽略的效果,特别是怎样在Python-numpy中构造向量。例如,首先设置a=np.random.randn(5),这样会生成存储在数组 中的5个高斯随机数变量。之后输出 a,此时调用shape(形状)函数,可以得到这个矩阵的结构。这在Python中被称作一个一维数组。它既不是一个行向量也不是一个列向量,这也导致它有一些不是很直观的效果。举个例子,如果我输出一个转置阵,最终结果它会和看起来一样。而如果我输出和的转置阵的内积,我们以为会得到的结果是一个矩阵,但是其实只会得到一个数,是两个数的叉乘。

import numpy as np

a = np.random.randn(5)
print(a)

print(a.shape)

print(a.T)

print(np.dot(a,a.T))
b = a.reshape(1,5)
print(b)
print(np.dot(a,b.T))

运行结果:

np.random.randn(d0, d1,…, dn) randn函数返回一个或一组样本,具有标准正态分布。

dn表示每个维度,返回值为指定维度的array

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值