深度学习-逻辑回归-单个神经元

文章目录

逻辑回归的目的

逻辑回归是解决二分问题,判断样本属于正类的概率是多大,0-1之间

找到一组最佳的权重(w1,w2,w3,...) ,b,使得模型预测的概率 P(Y=1) 尽可能接近样本的真实标签(1 或 0)。

计算过程

前向传播过程如下:

假设有一个简单的神经网络层,包括输入 ( x )、权重 ( w )、偏置 ( b ) 和激活函数( σ),输出为 ( a )。损失函数为 ( L ),我们希望计算损失函数对权重 ( w ) 的梯度。
输入特征x 线性变换:z=w*x+b 激活函数:a=σ(z) 输出预测概率a

σ ( z ) = 1 1 + e − z \sigma(z) = \frac{1}{1 + e^{-z}} σ(z)=1+e−z1

损失函数,也就是误差

复制代码
损失计算:L=Loss(a,y),其中 y 是真实标签,a是预测值

L ( y ^ , y ) = − y log ⁡ ( y ^ ) − ( 1 − y ) log ⁡ ( 1 − y ^ ) L(\hat{y}, y) = - y \log(\hat{y}) - (1 - y) \log(1 - \hat{y}) L(y^,y)=−ylog(y^)−(1−y)log(1−y^)

最常见的损失函数就是最小二乘法损失函数:1/2∑(目标值 - 预测值)²。即E_{total}=\frac{1}{2}(T-Y)^{2}。通过最小化均方误差,可以求解出最优的模型参数W,使得模型的预测结果Y与目标值之间T的平方差最小化。这样的损失函数对异常值比较敏感,因为它会对差值进行平方,导致异常值的差异被放大。

训练的目的是把L(y^,y)趋近0,让损失最小,就是趋向于最低点

其有w与b两个变量

反向传播,更新权重W

这里的 α是学习率,是调整的幅度,w的优化就是通过减去w的偏导数来达成的

J和L是一样的含义,都是损失函数

偏导数如何求(计算梯度)

反向传播中的梯度计算

  1. 计算损失函数 L L L 对激活值 a a a 的梯度:
    ∂ L ∂ a \frac{\partial L}{\partial a} ∂a∂L

  2. 计算激活函数 σ \sigma σ 对 z z z 的梯度:
    ∂ a ∂ z = σ ′ ( z ) \frac{\partial a}{\partial z} = \sigma'(z) ∂z∂a=σ′(z)

  3. 计算 z z z 对权重 w w w 的梯度:
    ∂ z ∂ w = x \frac{\partial z}{\partial w} = x ∂w∂z=x

    就是w

  4. 使用链式法则计算损失函数 L L L 对权重 w w w 的梯度:
    ∂ L ∂ w = ∂ L ∂ a ⋅ ∂ a ∂ z ⋅ ∂ z ∂ w \frac{\partial L}{\partial w} = \frac{\partial L}{\partial a} \cdot \frac{\partial a}{\partial z} \cdot \frac{\partial z}{\partial w} ∂w∂L=∂a∂L⋅∂z∂a⋅∂w∂z

    4中就是w关于L的偏导数

这是L
L ( y ^ , y ) = − y log ⁡ ( y ^ ) − ( 1 − y ) log ⁡ ( 1 − y ^ ) L(\hat{y}, y) = - y \log(\hat{y}) - (1 - y) \log(1 - \hat{y}) L(y^,y)=−ylog(y^)−(1−y)log(1−y^)

这是a
σ ( z ) = 1 1 + e − z \sigma(z) = \frac{1}{1 + e^{-z}} σ(z)=1+e−z1

这是z
z = w ∗ x + b z=w*x+b z=w∗x+b
问题:计算出 J J J 关于 z z z 的导数

  • ∘ d J d z = d J d a ∗ d a d z \circ\ \dfrac{dJ}{dz}=\dfrac{dJ}{da}*\dfrac{da}{dz} ∘ dzdJ=dadJ∗dzda
  • ∘ d J d a = − y a + 1 − y 1 − a \circ\ \dfrac{dJ}{da} = -\dfrac{y}{a} + \dfrac{1 - y}{1 - a} ∘ dadJ=−ay+1−a1−y
  • ∘ d a d z = a ( 1 − a ) \circ\ \dfrac{da}{dz} = a(1 - a) ∘ dzda=a(1−a)

d J d z = d J d a ⋅ d a d z = a − y \frac{dJ}{dz} = \frac{dJ}{da} \cdot \frac{da}{dz} = a - y dzdJ=dadJ⋅dzda=a−y
d w 1 = d z d w 1 = ( a − y ) ⋅ x 1 dw_1 = \frac{dz}{dw_1} = (a - y) \cdot x_1 dw1=dw1dz=(a−y)⋅x1
d w 2 = d z d w 2 = ( a − y ) ⋅ x 2 dw_2 = \frac{dz}{dw_2} = (a - y) \cdot x_2 dw2=dw2dz=(a−y)⋅x2
d b = d z db = dz db=dz

在神经网络中,偏置项 b 是​​全局共享参数​​:,偏置项 b 影响所有样本的输出

计算梯度代码现

python 复制代码
import numpy as np

# 激活函数及其导数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))
#倒数
def sigmoid_derivative(x):
    return sigmoid(x) * (1 - sigmoid(x))

# 假设数据
x = np.array([0.5])  # 输入
w = np.array([0.2])  # 权重
b = 0.1  # 偏置
y = np.array([0.7])  # 实际目标

# 前向传播
z = w * x + b
a = sigmoid(z)

# 计算损失(均方误差)
loss = 0.5 * (a - y) ** 2
print(f'损失对权重的梯度: {loss}')

# 反向传播(链式法则)
dL_da = a - y  # 损失函数对激活值的梯度
da_dz = sigmoid_derivative(z)  # 激活函数对 z 的梯度
dz_dw = x  # z 对权重 w 的梯度

# 使用链式法则计算损失函数对权重的梯度
dL_dw = dL_da * da_dz * dz_dw

print(f'损失对权重的梯度: {dL_dw}')
#这个就是J对w的梯度,就是那个偏导数

完整代码实现

数学原理

  • 正向传播

    初始化,假设n个特征,m个样本
    J = 0 J=0 J=0
    W = n p . z e r o s ( n , 1 ) W=np.zeros(n,1) W=np.zeros(n,1)
    b = 0 b=0 b=0
    Z = n p . d o t ( W T , X ) + b Z=np.dot(W^{T},X)+b Z=np.dot(WT,X)+b
    A = σ ( Z ) A=\sigma(Z) A=σ(Z)

  • 反向传播

    每个样本梯度计算过程为:
    d Z = A − Y dZ = A - Y dZ=A−Y
    d W = 1 m X d Z T dW = \frac{1}{m} XdZ^{T} dW=m1XdZT
    d b = 1 m np.sum ( d Z ) db = \frac{1}{m} \text{np.sum}(dZ) db=m1np.sum(dZ)

更新
W : = W − α d W W := W - \alpha dW W:=W−αdW
b : = b − α d b b := b - \alpha db b:=b−αdb

  • dz是(1,m)的矩阵,m是样本的数目
  • X是(n,m)的矩阵,n是特征x的数目,m是样本数,得到的dW是 ( n ∗ m ) ( m ∗ 1 ) − > ( n , 1 ) (n*m )( m*1)->(n,1) (n∗m)(m∗1)−>(n,1)的矩阵,
    是平均下来每个特征 x n xn xn对应的 w n wn wn的平均梯度
  • z = w 1 ∗ x 1 + w 2 ∗ x 2 + w 3 ∗ x 3 + . . . . + w n ∗ x n z=w1*x1+w2*x2+w3*x3+....+wn*xn z=w1∗x1+w2∗x2+w3∗x3+....+wn∗xn
  • 各个函数
python 复制代码
import numpy as np
#激活函数sigmoid()
def basic_sigmoid(x):
    s = 1 / (1 + np.exp(-x))
    return s

#初始化W,b
def initialize_weights(shape):
    w=np.zeros((shape,1))
    b=0
    #这里w全为1,后面会迭代,1只是初始值
    assert(w.shape == (shape,1))
    assert(isinstance(b,float) or isinstance(b,int))
    #assert检测类型是否正确,相当于异常检测
    return w,b

#前向传播与反向传播,propagate传播
#用于得到 平均损失cost,dW均值,与db,便于后续优化optimize
def propagate(W,b,X,Y):
    #W权重(n,1),b是偏置向量,X是输入的m个样本的(n,m)矩阵,Y是实际值用于反向传播

    m=X.shape[1]  #获取X的列数,即样本的个数
    #前向传播
    #np.dot()是矩阵乘法,W,T大写代表矩阵,+b是矩阵结果的每一项都+b
    #得到的A是(1,m)的一维矩阵
    A=basic_sigmoid(np.dot(W.T,X)+b)

    #计算损失
    #操作对象是矩阵,想达到向量化运算,用np
    cost=-1/m*np.sum(np.log(A)+(1-Y)*np.log(1-A)) #求损失平均值,负的(-),越接近0正确率越高

    ##反向传播
    #下面得到的是dW是w得平均值(n,1)矩阵
    dz=A-Y   #得到(1,m)
    dW=1/m*np.dot(X,dz.T)  #n*m M*1->(n,1)
    db=1/m*np.sum(dz)      #偏置向量怎么调?

    assert(dW.shape ==W.shape)
    assert(db.dtype == float)
    #np.squeeze(cost)确保cost是一个标量(不是矩阵)
    cost=np.squeeze(cost)
    assert(cost.shape == ())
    grads={
        "dW":dW,
        "db":db
    }
    return grads,cost

#优化
def optimize(W,b,X,Y,num_iterations,learning_rate):
    '''
参数
 w:权重;b:偏置;x:特征; y:目标值;num_iterations:总迭代次数;learning_rate:学习率
Returns:
params:更新后的参数字典; grads:梯度 ; costs:损失结果
    '''
    costs=[] #用于存放损失的变化
    for i in range(num_iterations):
        grads,cost=propagate(W,b,X,Y)
        #取出dW的平均值梯度(n,1)矩阵,db
        dW=grads['dW']
        db=grads['db']

        #根据优化公式更新
        w=W-learning_rate*dW #权重
        b=b-learning_rate*db #偏置

        #记录cost的变化,每隔100个记录一次
        if i % 100==0:
            costs.append(cost)
            print("损失结果 %i,%f" %(i,cost))

        params={
            "w":w,
            "b":b
        }#更新之后的线性变换的参数
        grads={
            "dW":dW,
            "db":db
        }#没变,还是grads,cost=propagate(W,b,X,Y)
    return params,grads,costs

#预测  (权重,偏置,输入)
#返回的是一个(1,m)的矩阵
def predict(W , b, X):
    m=X.shape[1] #得到X列数,即样本个数 X(n,m)
    Y_prediction=np.zeros(1,m) #定义一个存放预测值的(1,m)矩阵
    W=W.reshape(X.shape[0],1)        #定义一个(n,1)的矩阵,用于存放w1-wn的权重

    #预测
    A=basic_sigmoid(np.dot(W.T,X)+b)  #(1,m)的预测值

    for i in range(A.shape[1]): #循环m次
        if A[0,i]<=0.5:
            Y_prediction[0,i]=0
        if A[0,i]>=0.5:
            Y_prediction[0,i]=1

    assert(Y_prediction.shape==(1,m))

    return Y_prediction

#汇总函数
def model(X_train,Y_train,X_test,Y_test,num_iterations=2000,learning_rate=0.5):
    # 初始化W,b
    W,b=initialize_weights(X_train)

    #梯度下降优化
    #应该是这个吧X_train,Y_train
    params,grads,costs=optimize(W,b,X_train,Y_train,num_iterations,learning_rate)

    W=params['W']
    b=params['b']
    Y_prediction_train=predict(W,b,X_train)
    Y_prediction_test=predict(W,b,X_test)

    #打印准确率
    print("训练集准确率:{}".format(100-np.mean(np.abs(Y_prediction_train-Y_train))*100))
    print("测试集准确率:{}".format(100-np.mean(np.abs(Y_prediction_test-Y_test))*100))

    #数据汇总
    d={
        "costs":costs,
        "Y_prediction_train":Y_prediction_train,
        "Y_prediction_test":Y_prediction_test,
        "W":W,
        "b":b,
        "learning_rate":learning_rate,
        "num_iterations":num_iterations
    }
    return d

if __name__=="__main__":
    # 最后运行模型
    model_result = model(X_train, Y_train, X_test, Y_test)
    print(model_result)
  • 总体实现 单神经元
python 复制代码
import numpy as np

# 训练集
X_train = np.array([
    [0.1, 0.3, 0.5, 0.7, 0.9, 0.2, 0.4, 0.6],  # 特征1
    [1.2, 0.8, 1.0, 1.5, 0.5, 1.1, 0.9, 1.3]  # 特征2
])  # (2, 8) 特征矩阵,2个特征,8个样本

Y_train = np.array([
    [0, 0, 0, 1, 1, 0, 0, 1]
])  # (1, 8) 标签向量

# 测试集
X_test = np.array([
    [0.3, 0.8, 0.2, 0.5],  # 特征1
    [1.0, 0.7, 1.1, 0.9]  # 特征2
])  # (2, 4) 特征矩阵,2个特征,4个样本

Y_test = np.array([
    [0, 1, 0, 1]
])  # (1, 4) 标签向量


# 激活函数sigmoid()
def basic_sigmoid(x):
    s = 1 / (1 + np.exp(-x))
    return s


# 初始化W,b
def initialize_weights(shape):
    w = np.zeros((shape, 1))
    b = 0
    assert w.shape == (shape, 1)
    assert isinstance(b, float) or isinstance(b, int)
    return w, b


# 前向传播与反向传播
def propagate(W, b, X, Y):
    m = X.shape[1]  # 样本个数

    # 前向传播 (添加了数值稳定性)
    A = basic_sigmoid(np.dot(W.T, X) + b)

    # 计算损失 (避免log(0))
    epsilon = 1e-5
    cost = -1 / m * np.sum(Y * np.log(A + epsilon) + (1 - Y) * np.log(1 - A + epsilon))

    # 反向传播
    dz = A - Y
    dW = 1 / m * np.dot(X, dz.T)
    db = 1 / m * np.sum(dz)

    # 验证
    assert dW.shape == W.shape
    assert isinstance(db, float)
    cost = np.squeeze(cost)
    assert cost.shape == ()

    grads = {"dW": dW, "db": db}
    return grads, cost


# 优化
def optimize(W, b, X, Y, num_iterations, learning_rate):
    costs = []

    # 复制参数避免修改原始值
    W = W.copy()
    b = b

    for i in range(num_iterations):
        grads, cost = propagate(W, b, X, Y)
        dW = grads["dW"]
        db = grads["db"]

        # 更新参数
        W = W - learning_rate * dW
        b = b - learning_rate * db

        # 每100次记录一次损失
        if i % 100 == 0:
            costs.append(cost)
            print(f"迭代 {i}, 损失: {cost:.6f}")

    # 记录最终损失
    _, final_cost = propagate(W, b, X, Y)
    costs.append(final_cost)
    print(f"最终迭代 {num_iterations}, 损失: {final_cost:.6f}")

    params = {"W": W, "b": b}
    grads = {"dW": dW, "db": db}
    return params, grads, costs


# 预测
def predict(W, b, X):
    m = X.shape[1]
    Y_prediction = np.zeros((1, m))  # 修正这里:np.zeros((1, m))

    # 确保W是列向量
    if len(W.shape) == 1:
        W = W.reshape(-1, 1)

    # 计算预测值
    A = basic_sigmoid(np.dot(W.T, X) + b)

    # 二分预测
    Y_prediction = (A > 0.5).astype(int)

    assert Y_prediction.shape == (1, m)
    return Y_prediction


# 模型汇总
def model(X_train, Y_train, X_test, Y_test, num_iterations=2000, learning_rate=0.5):
    # 初始化
    n_features = X_train.shape[0]
    W, b = initialize_weights(n_features)

    # 优化
    params, grads, costs = optimize(W, b, X_train, Y_train, num_iterations, learning_rate)

    # 获取参数
    W = params["W"]
    b = params["b"]

    # 预测
    Y_prediction_train = predict(W, b, X_train)
    Y_prediction_test = predict(W, b, X_test)

    # 计算准确率
    train_accuracy = 100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100
    test_accuracy = 100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100

    print("\n模型训练结果:")
    print(f"训练集准确率: {train_accuracy:.2f}%")
    print(f"测试集准确率: {test_accuracy:.2f}%")

    # 结果汇总
    result = {
        "costs": costs,
        "Y_prediction_train": Y_prediction_train,
        "Y_prediction_test": Y_prediction_test,
        "W": W,
        "b": b,
        "learning_rate": learning_rate,
        "num_iterations": num_iterations,
        "train_accuracy": train_accuracy,
        "test_accuracy": test_accuracy
    }
    return result


if __name__ == "__main__":
    # 运行模型
    model_result = model(
        X_train=X_train,
        Y_train=Y_train,
        X_test=X_test,
        Y_test=Y_test,
        num_iterations=2000,
        learning_rate=0.05
    )

    print("\n最终参数:")
    print(f"权重 W: \n{model_result['W']}")
    print(f"偏置 b: {model_result['b']:.4f}")

总的来说

逻辑回归只会给出 0 1的判断,而我们优化的就是减小这个0 1判断的误差

相关推荐
chaojihaomai3 小时前
AI电商商品图生成中的材质保真问题——扩散模型重建优先级分析与锁定式方案
人工智能·材质
大模型探索者5 小时前
2026 企业智能体平台选型指南:从通用到行业深耕,怎么选?
大数据·人工智能
深圳行云创新5 小时前
北极星知识图谱平台|太空越来越“拥挤”,知识图谱如何预测空间碎片碰撞风险?
人工智能·知识图谱
Am-Chestnuts5 小时前
国产AI多轮对话归档与多格式导出实践
人工智能·word
麻瓜生活睁不开眼6 小时前
Android16修改全局桌面视图边框四直角显示为弧边圆角
android·java·深度学习
workflower6 小时前
装备企业的 AI 路线图
人工智能·深度学习·机器学习·设计模式·机器人
AKAMAI7 小时前
Linode接口及默认防火墙现已全面开放使用
人工智能·云计算
前端开发江鸟7 小时前
RAG 回答错了,问题到底出在召回、重排,还是生成?
人工智能
美狐美颜SDK开放平台7 小时前
直播app开发如何实现主播级美颜效果?美颜sdk开发方案详解
人工智能·音视频·美颜sdk·视频美颜sdk·美颜api
东方小月8 小时前
从零开发一个 Coding Agent(四):使用状态机校验大模型事件流
前端·人工智能·后端