【学习报告】9.26-10.2

本文深入解析逻辑回归原理,包括其在二分类问题中的应用、损失函数的设计、梯度下降法的应用及参数更新策略,并介绍了向量化在提高计算效率方面的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

逻辑回归

逻辑回归用于二分类问题,给定一个输入特征向量X,输出一个预测值y ^^^ ,来告诉我们y=1的概率。

假设X是一个nx维向量(相当于有nx个特征的特征向量),我们用w表示逻辑回归的参数,这也是nx维的向量,还有一个参数b,这是一个实数,所以y ^^^=w T x+b.

但是上述是一个关于X的线性函数,对于二分类问题不可行,因为我们想让y ^^^ 表示概率,那么它的取值范围[0,1],因此需要将y^^^ 带入simoid函数中。

sigmoid函数表达式为:

image-20220926165659982

图像如下:

image-20220926165750937

由图可以看出:当x很大时,输出接近于1,当x很小时,输出接近于0,满足我们二分类的要求。

逻辑回归的损失函数

损失函数又叫做误差函数,用来衡量算法的运行情况,来衡量预测输出值和实际值有多接近。一般我们用预测值和实际值的平方差或者它们平方差的一半,但是通常在逻辑回归中我们不这么做,因为当我们在学习逻辑回归参数的时候,会发现我们的优化目标不是凸优化,只能找到多个局部最优值,梯度下降法很可能找不到全局最优值,虽然平方差是一个不错的损失函数,但是我们在逻辑回归模型中会定义另外一个损失函数。
我们在逻辑回归中用到的损失函数是:

image-20220926171039592

我们的目标是使得损失函数尽可能小,

当y=1,L=-log(y^^),L尽可能小,也就是y^^ 尽可能大,也就是y^^^ 越接近y

当y=0,L=-log(1-y^^^) ,L尽可能小,也就是y^^^ 尽可能小,也就是y^^^ 越接近y

损失函数是在单个训练样本中定义的,它衡量的是算法在单个训练样本中表现如何

为了衡量算法在全部训练样本上的表现如何,我们需要定义一个算法的代价函数,算法的代价函数是对m个样本的损失函数求和然后除以m:

image-20220926171453943

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

梯度下降法

思想:不断迭代,从而找到最好的参数

假设代价函数的图像如下:

image-20220926173418571
  1. 可以用如图那个小红点来初始化参数w和b,也可以采用随机初始化的方法,对于逻辑回归几乎所有的初始化方法都有效,因为函数是凸函数,无论在哪里初始化,应该达到同一点或大致相同的点。

  2. 朝最陡的下坡方向走一步,不断地迭代(a为学习率,也就是步长)

image-20220926173751057
  1. 直到走到全局最优解或者接近全局最优解的地方

通过以上的三个步骤我们可以找到全局最优解,也就是代价函数(成本函数)J(w,b)这个凸函数的最小值点。

计算图

一个神经网络的计算,都是按照前向或反向传播过程组织的。首先我们计算出一个新的网络的输出(前向过程),紧接着进行一个反向传输操作。后者我们用来计算出对应的梯度或导数。计算图解释了为什么我们用这种方式组织这些计算过程。

例如:

image-20220926192900658

从左往右计算J的值,从右往左计算导数。

使用计算图求导数

实际上就是链式求导

已知:image-20220926195032116

求:

image-20220926195220699

逻辑回归中的梯度下降

image-20220927100112929 image-20220927100417403

假设只有一个样本,则代价函数如下:(a就是预测值,y是真实值)

image-20220927100834782

画出计算图:

image-20220927110500157

求偏导:

image-20220927111555864

更新参数:

image-20220927111905140

对于m个样本的逻辑回归

代价函数:

image-20220927170619090

求偏导:

若只有一个样本,则dw就是一个样本求偏导;若有m个样本,则dw就是m个样本的偏导的平均。

image-20220927171640363

最后更新参数:

image-20220927111905140

至此一轮迭代结束。

向量化

向量化是非常基础的去除代码中 for 循环的艺术,在在深度学习领域,运行向量化是一个关键的技巧。

在逻辑回归中,我们需要计算z=wT x + b,其中w,x都是列向量,因此如果用非向量化方法计算z,代码如下:

import numpy as np
import time

x = np.random.rand(100000)
w = np.random.rand(100000)
b = np.random.rand()
z = 0;
for i in range(10000):
    z += x[i] * w[i]
print(z)

向量化的方法,代码如下:

import numpy as np
import time

'''
dot(a,b):
当a和b是一维数组时,做点乘
当a和b是多维矩阵时,做矩阵乘法

a*b:对于位置元素相乘
'''
x = np.random.rand(100000)
w = np.random.rand(100000)
b = np.random.rand()
# np.dot(a,b):a和b做点乘
z = np.dot(x, w)+b
print(z)

现在做一个测试,看看哪个方法速度更快

import numpy as np
import time

x = np.random.rand(100000)
w = np.random.rand(100000)
b = np.random.rand()
z = 0;
s1 = time.time()
for i in range(100000):
    z += x[i] * w[i]
z += b
e1 = time.time()
print("非向量化的运行时间:" + str(1000 * (e1 - s1)) + "ms")

s2 = time.time()
z = np.dot(x, w) + b
e2 = time.time()
print("向量化的运行时间:" + str(1000 * (e2 - s2)) + "ms")

输出:image-20220927191607907

事实上,可以通过python的内置函数来替换for循环

逻辑回归的实现

假设X是n维的

原始版本的实现:需要两个for循环,十分低效

image-20220927195107173

设:

image-20220927200009217

那么:image-20220927200211591

一轮迭代结束。

import numpy as np


def sigmoid(x):
    # 直接返回sigmoid函数
    return 1. / (1. + np.exp(-x))


# 初始化
m = 100
n = 10
a = 0.001
iteration = 10000
X = np.random.randint(10, size=(n, m))
Y = np.random.randint(2, size=(1, m))  # 随机生成不大于2的n*1维矩阵
b = np.random.rand()
W = np.random.rand(n, 1)
# 实现
for i in range(iteration):
    Z = np.dot(W.T, X) + b #矩阵乘法
    A = sigmoid(Z)
    dZ = A - Y
    dW = np.dot(X, dZ.T) * (1 / m)
    db = np.sum(dZ) * (1 / m)
    loss = -(Y * np.log(A) + (1 - Y) * np.log(1 - A)) # 矩阵点乘
    loss = np.sum(loss) / m
    print(loss)
    W -= a * dW
    b -= a * db

Python中的广播

广播就是在水平方向上复制或者在垂直方向上复制,以得到符合要求的矩阵

import numpy as np
'''
A是一个3*4的矩阵
'''
A = np.array([[56, 0, 4.4, 68],
              [1.2, 104, 52, 8],
              [1.8, 135, 99, 0.9]])

cal = A.sum(axis=0)  # axis=0:每一列求和,axit=1:每一行求和
print(cal)
输出:[ 59.  239.  155.4  76.9]

'''
 A是3*4的矩阵,cal是1*4的矩阵,不能直接相除,
 所以cal在垂直方向复制3次,变成3*4的矩阵,
 然后对应位置元素相除
'''
percentage = 100 * A / cal.reshape(1, 4)
print(percentage)
输出:[[94.91525424  0.          2.83140283 88.42652796]
 [ 2.03389831 43.51464435 33.46203346 10.40312094]
 [ 3.05084746 56.48535565 63.70656371  1.17035111]]

关于numpy的注意点

当创建一个行向量时

a = np.random.randn(1, 5)

当创建一个列向量时

a = np.random.randn(5, 1)

打印矩阵的维数

a = np.random.randn(1, 5)
print(a.shape)

矩阵转置

a = np.random.randn(1, 5)
a = a.reshape(5, 1)

numpy用法总结

指数函数

'''
np.exp(x)
x可以是一个数,也可以是一个矩阵
返回e的x方
''' 
import numpy as np
x = np.array([1, 2, 3])
print(np.exp(x))

输出:[ 2.71828183 7.3890561 20.08553692]

sigmoid函数

函数原型

sigmoid(x)=1/(1+exp(-x))

导数

s=sigmoid(x)
ds=s*(1-s)

reshape

# 如果将v的shape(a,b,c),转为(a*b,c),v.shape[0] = a ; v.shape[1] = b ; v.shape[2] = c
v = v.reshape((v.shape[0]*v.shape[1], v.shape[2])) 

归一化

np.linalg.norm(x,ord=None,axis=None,keepdims=False)
```
x:矩阵,可以是一维的
ord:范数类型,默认二范数,
ord=2 二范数
ord=1 一范数 |x1|+|x2|+|x3|+...+|xn|
ord=np.inf 无穷范数 max(|xi|)
axis=0:按列处理
axit=1:按行处理
keepdims:表示是否保持矩阵的二位特性,True表示保持,False表示不保持,默认为False
```

通过归一化,可以使得梯度下降的更快

# GRADED FUNCTION: normalizeRows

def normalizeRows(x):
    x -- A numpy matrix of shape (n, m)
    norm=np.linalg.norm(x,axis=1) # norm是n*1,不过是一维的
    x=x/norm.reshape(x.shape[0],1) # 按行归一化,所以x的每一个元素除与所在行的norm,涉及到广播
    return x
    
x = np.array([
    [0, 3, 4],
    [1, 6, 4]])
print("normalizeRows(x) = " + str(normalizeRows(x)))


输出:normalizeRows(x) = [[0. 0.6 0.8 ]
[0.13736056 0.82416338 0.54944226]]

np.sum()

np.sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue)
axis=0 按列
axit=1 按列
keepdims =True 将保持a的维度
def softmax(x):
    x_exp=np.exp(x)
    rowSum=np.sum(x_exp,axis=1).reshape(x.shape[0],1)
    s=x_exp/rowSum
    return s

softmax表达式:

image-20221002205616243

向量化

np.outer()

函数作用:通常用来计算两个向量的外积,第一个数组的每一个元素×第二个数组的各个元素
函数调用方法:

np.outer(a,b,out=None)
a:第一个输入向量,假设维度(M,1)
b:第二个输入向量,假设维度(N,1)
out:设置结果的保存位置,通常使用默认值None,不需要做多余处理。
有返回值,返回一个维度为(M,N)的ndarray数组。

np.multiply(a,b)

对应元素相乘

np.dot(a,b)

(1)如果a和b都是一维的,那么结果就是普通的內积(inner product)。
image-20221002212253325

(2)如果a和b都是二维的,运算等同于矩阵乘法(Dot product / matrix product)。

image-20221002212331076

(3) 矩阵x为m×n阶,向量y为n阶向量,则矩阵x和向量y可以进行乘法运算,结果为m阶向量。进行运算时,会首先将后面一项进行自动转置操作,之后再进行乘法运算。

import numpy as np

x = np.array([[1, 2, 3],
              [3, 4, 4]])
y = np.array([1, 2, 3])
result = np.dot(x, y)

print(result)
print("x阶数:" + str(x.shape))
print("y阶数:" + str(y.shape))
print("result阶数:" + str(result.shape))

输出:

[14 23]
x阶数:(2, 3)
y阶数:(3,)
result阶数:(2,)

numpy.squeeze()函数

作用:从数组的形状中删除单维度条目,即把shape中为1的维度去掉

#例1
import numpy as np
a  = np.arange(10).reshape(1,10)
a
->array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
a.shape
->(1, 10)
b = np.squeeze(a)
b
->array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
b.shape
->(10,)
#例2
c  = np.arange(10).reshape(2,5)
c
->array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
np.squeeze(c)
->array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

综上可知,np.squeeze()函数可以删除数组形状中的单维度条目,即把shape中为1的维度去掉,但是对非单维的维度不起作用。

np.zeros()

numpy.zeros(shape, dtype=float)
shape:创建的新数组的形状(维度)。
dtype:创建新数组的数据类型。
返回值:给定维度的全零数组。
import numpy as np

array = np.zeros([2, 3])
print(array)
print(array.dtype)
"""
result:
[[0. 0. 0.]
 [0. 0. 0.]]
float64
"""

plt

1.plt.legned
plt.legend(loc,)
loc:
'best' : 0, 自适应方式
'upper right' : 1,
'upper left' : 2,
'lower left' : 3,
'lower right' : 4,
'right' : 5,
'center left' : 6,
'center right' : 7,
'lower center' : 8,
'upper center' : 9,
'center' : 10

2.plt.figure
plt.figure(figsize=(14, 6), dpi=80)#设置绘图区域的大小和像素

3.plt.xticks
plt.xticks(new_year)#设置x轴的刻度线为new_year,new_year可以为数组

4.plt.xlabel
plt.xlabel('year')#x轴标签

5.plt.plot
plt.plot(number, color='blue', label="actual value")#将实际值的折线设置为蓝色

6.两个图分开
fig, axes = plt.subplots(2, 1, sharex=true,figsize=(10,10))
axes[0].plot(range (len(data20)),data20,'r')
axes[1].plot(range (len(data40)),data40,'b')

7、画竖直线
plt.axvline(99, linestyle="dotted", linewidth=4, color='r')#99表示横坐标

8、图片保存
plt.savefig('timeseries_y.jpg')

转置技巧

假设一个数组a.shape(x,y,z)
如果将它转成(y*z,x)
笨方法:
a=a.reshape(a.shape[1]*a.shape[2],a.shape[0])
简单方法
a=a.reshape(a.shape[0],-1).T

预处理的三个通常步骤

  1. 计算出数据集的维度
  2. reshape数据集
  3. 标准化数据集
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值