吴恩达机器学习作业ex4:反向神经网络学习(Python实现)详细注释

news2024/11/15 11:48:40

文章目录

  • 1.神经网络
    • 1.1 可视化数据
    • 1.2 模型表示
    • 1.3 前馈和成本函数
    • 1.4 正则化代价函数
  • 2.反向传播
    • 2.1 Sigmoid的导数
    • 2.2随机初始化
    • 2.3 反向传播
    • 2.4梯度检测
    • 2.5 正则化神经网络
    • 2.6 优化参数
  • 3.可视化隐藏层

1.神经网络

在上一个练习中,您为神经网络实现了前馈传播,并利用我们提供的权重来预测手写数字。在本练习中,您将实现反向传播算法来学习神经网络的参数。
提供的脚本 ex4.m 将帮助您逐步完成本练习。

1.1 可视化数据

在 ex4.m 的第一部分中,代码将加载数据并通过调用函数 displayData 将其显示在二维图上(图 1)。
在这里插入图片描述
这是您在上一个练习中使用的相同数据集。ex3data1.mat 中有 5000 个训练示例,其中每个训练示例都是 20 像素 x 20 像素的数字灰度图像。每个像素都由一个浮点数表示,表示该位置的灰度强度。20 x 20 像素网格被“展开”为 400 维向量。这些训练示例中的每一个都成为数据矩阵 X 中的一行。这为我们提供了一个 5000 x 400 矩阵 X,其中每一行都是手写数字图像的训练示例。
在这里插入图片描述
训练集的第二部分是一个 5000 维向量 y,其中包含训练集的标签。为了与 Octave/MATLAB 索引(其中没有零索引)更兼容,我们将数字零映射到值十。因此,“0”数字被标记为“10”,而“1”到“9”的数字按其自然顺序标记为“1”到“9”。
与上一节作业几乎一样

import numpy as np
import matplotlib.pyplot as plt
from scipy.io import loadmat
import scipy.optimize as opt
from sklearn.metrics import classification_report  # 这个包是评价报告
def load_mat(path):
    '''读取数据'''
    data = loadmat('ex4data1.mat')  # return a dict
    X = data['X']
    y = data['y'].flatten()
    
    return X, y  
def plot_100_images(X):
    """随机画100个数字"""
    index = np.random.choice(range(5000), 100)  # 从范围5000中随机选择100个索引
    images = X[index]  # 根据随机索引选择100个图像
    fig, ax_array = plt.subplots(10, 10, sharey=True, sharex=True, figsize=(8, 8))  # 创建一个10x10的子图,所有子图共享x轴和y轴,图像大小为8x8英寸
    for r in range(10):  # 遍历10行
        for c in range(10):  # 遍历10列
            ax_array[r, c].matshow(images[r*10 + c].reshape(20,20).T, cmap='gray_r')  # 将每个图像重塑为20x20并转置,然后在子图中显示为反转的灰度图
    plt.xticks([])  # 去除x轴刻度
    plt.yticks([])  # 去除y轴刻度
    plt.show()  # 显示图像

X,y = load_mat('ex4data1.mat')
plot_100_images(X)

如图
在这里插入图片描述

1.2 模型表示

我们的神经网络如图 2 所示。它有 3 层——输入层、隐藏层和输出层。回想一下,我们的输入是数字图像的像素值 3。由于图像的大小为 20 × 20,因此我们有 400 个输入层单元(不计算始终输出 +1 的额外偏置单元)。训练数据将由 ex4.m 脚本加载到变量 X 和 y 中。
我们已为您提供一组经过训练的网络参数(Θ(1)、Θ(2))。这些参数存储在 ex4weights.mat 中,并将由 ex4.m 加载到 Theta1 和 Theta2 中。这些参数的尺寸适合第二层有 25 个单元和 10 个输出单元(对应 10 个数字类别)的神经网络。
在这里插入图片描述

from sklearn.preprocessing import OneHotEncoder

def expand_y(y):
    result = []
    # 把y中每个类别转化为一个向量,对应的label值在向量对应位置上置为1
    for i in y:
        y_array = np.zeros(10)  # 创建一个长度为10的全零向量
        y_array[i-1] = 1  # 将对应类别的位置置为1
        result.append(y_array)  # 将转换后的向量添加到结果列表中
    
    '''
    # 或者用sklearn中OneHotEncoder函数
    encoder = OneHotEncoder(sparse=False)  # 使用OneHotEncoder并设置sparse=False以返回数组而不是矩阵
    y_onehot = encoder.fit_transform(y.reshape(-1, 1))  # 将y转换为二维数组并进行独热编码
    return y_onehot  # 返回独热编码后的数组
    ''' 
    
    return np.array(result)  # 将结果列表转换为NumPy数组并返回

# 加载数据的函数
def load_mat(path):
    data = loadmat(path)
    return data['X'], data['y']

# 调用load_mat函数加载数据
raw_X, raw_y = load_mat('ex4data1.mat')

# 在特征矩阵X的第一列插入全1列,用于偏置项
X = np.insert(raw_X, 0, 1, axis=1)

# 将标签y进行独热编码
y = expand_y(raw_y)

# 打印X和y的形状
X.shape, y.shape
'''
((5000, 401), (5000, 10))
'''
def load_weight(path):
    data = loadmat(path)  # 使用loadmat函数加载指定路径的MAT文件
    return data['Theta1'], data['Theta2']  # 返回文件中的Theta1和Theta2
# 从文件中加载预训练的权重
t1, t2 = load_weight('ex4weights.mat')

# 查看权重矩阵的形状
t1.shape, t2.shape
# 预期输出: ((25, 401), (10, 26))
def serialize(a, b):
    '''展开参数'''
    return np.r_[a.flatten(), b.flatten()]

def deserialize(seq):
    '''提取参数'''
    return seq[:25*401].reshape(25, 401), seq[25*401:].reshape(10, 26)

# 扁平化参数,25*401+10*26=10285
theta = serialize(t1, t2)
theta.shape  # (10285,)

1.3 前馈和成本函数

现在,你将实现神经网络的成本函数和梯度。首先,完成 nnCostFunction.m 中的代码以返回成本。回想一下,神经网络的成本函数(无正则化)是
在这里插入图片描述
其中 hθ(x(i)) 的计算方式如图 2所示,K = 10 是可能的标签总数。请注意,hθ(x(i))k = a(3) k 是第 k 个输出单元的激活值(输出值)。另外,回想一下,虽然原始标签(在变量 y 中)是 1、2、…、10,但为了训练神经网络,我们需要将标签重新编码为仅包含值 0 或 1 的向量,因此
在这里插入图片描述
您应该实现前馈计算,为每个示例 i 计算 hθ(x(i)),并将所有示例的成本相加。您的代码还应该适用于任意大小、任意数量标签的数据集(您可以假设始终至少有 K ≥ 3 个标签)。
实现说明:矩阵 X 包含行中的示例(即 X(i,:)’ 是第 i 个训练示例 x (i),表示为 n × 1 向量。)完成 nnCostFunction.m 中的代码后,您需要将 1 的列添加到 X 矩阵。神经网络中每个单元的参数在 Theta1 和 Theta2 中表示为一行。具体而言,Theta1 的第一行对应于第二层中的第一个隐藏单元。您可以使用 for 循环遍历示例来计算成本。

import numpy as np

def sigmoid(z):
    '''计算sigmoid函数'''
    return 1 / (1 + np.exp(-z))

def feed_forward(theta, X):
    '''计算每层的输入和输出'''
    t1, t2 = deserialize(theta)  # 将展开的一维参数还原为权重矩阵

    a1 = X  # 输入层的激活值,即输入数据
    z2 = a1 @ t1.T  # 计算隐藏层的输入,a1与第一层权重矩阵t1的转置相乘
    a2 = np.insert(sigmoid(z2), 0, 1, axis=1)  # 计算隐藏层的激活值,并插入偏置单元
    z3 = a2 @ t2.T  # 计算输出层的输入,a2与第二层权重矩阵t2的转置相乘
    a3 = sigmoid(z3)  # 计算输出层的激活值,即网络的预测结果
    
    return a1, z2, a2, z3, a3  # 返回每层的输入和输出

# 调用 feed_forward 函数进行神经网络的前向传播
a1, z2, a2, z3, h = feed_forward(theta, X)

# 在这里:
# theta 是神经网络的权重参数
# X 是输入的特征矩阵

# 返回值包括:
# a1: 输入层的激活值
# z2: 第一个隐藏层的加权输入
# a2: 第一个隐藏层的激活值
# z3: 输出层的加权输入
# h: 神经网络的预测输出

def cost(theta, X, y):
    # 使用 feed_forward 函数计算神经网络的前向传播结果
    a1, z2, a2, z3, h = feed_forward(theta, X)
    
    # 初始化损失函数 J
    J = 0
    
    # 遍历每一个样本
    for i in range(len(X)):
        # 计算交叉熵损失的第一部分
        first = - y[i] * np.log(h[i])
        
        # 计算交叉熵损失的第二部分
        second = (1 - y[i]) * np.log(1 - h[i])
        
        # 将第一部分和第二部分求和累加到总损失 J 中
        J = J + np.sum(first - second)
    
    # 计算平均损失
    J = J / len(X)
    
    # 返回平均损失 J
    return J
'''
# or just use vectorization
J = - y * np.log(h) - (1 - y) * np.log(1 - h)
return J.sum() / len(X)
'''
这段代码用一行简洁地实现了与上述循环代码相同的功能,但使用了向量化操作,这在计算上通常更有效率和简洁。

1.4 正则化代价函数

具有正则化的神经网络的成本函数由下式给出:
在这里插入图片描述
您可以假设神经网络只有 3 层 - 输入层、隐藏层和输出层。但是,您的代码应该适用于任意数量的输入单元、隐藏单元和输出单元。虽然我们已明确列出了 Θ(1) 和 Θ(2) 的索引以便于理解,但请注意,您的代码通常适用于任何大小的 Θ(1) 和 Θ(2)。请注意,您不应该正则化对应于偏差的项。对于矩阵 Theta1 和 Theta2,这对应于每个矩阵的第一列。您现在应该将正则化添加到成本函数中。请注意,您可以先使用现有的 nnCostFunction.m 计算未正则化的成本函数 J,然后再添加正则化项的成本。完成后,ex4.m 将使用已加载的 Theta1 和 Theta2 参数集以及 λ = 1 调用您的 nnCostFunction。您应该看到成本约为 0.383770。

# 定义正则化损失函数
def regularized_cost(theta, X, y, l=1):
    '''正则化时忽略每层的偏置项,也就是参数矩阵的第一列'''

    # 反序列化 theta 为两个参数矩阵 t1 和 t2
    t1, t2 = deserialize(theta)
    
    # 计算正则化项(不包括偏置项),即每层参数矩阵的第一列被忽略
    reg = np.sum(t1[:,1:] ** 2) + np.sum(t2[:,1:] ** 2)  # 也可以使用 np.power(a, 2) 函数

    # 计算正则化损失值
    return l / (2 * len(X)) * reg + cost(theta, X, y)
regularized_cost(theta, X, y, 1)  # 0.38376985909092354

2.反向传播

在本练习的这一部分,您将实现反向传播算法,以计算神经网络成本函数的梯度。您需要完成nnCostFunction.m文件,以便它返回适当的梯度值grad。一旦计算出梯度,您就可以使用高级优化器(如fmincg)来最小化成本函数J(θ)来训练神经网络。
您将首先实现反向传播算法,以计算(未正则化)神经网络参数的梯度。在您已验证未正则化情况下的梯度计算正确之后,您将实现正则化神经网络的梯度。

2.1 Sigmoid的导数

为了帮助您开始练习的这一部分,您将首先实现s型梯度函数。s型函数的梯度可以是
计算为
在这里插入图片描述

def sigmoid_gradient(z):
    return sigmoid(z) * (1 - sigmoid(z))

2.2随机初始化

在训练神经网络时,随机初始化参数对于打破对称性非常重要。随机初始化的一个有效策略是在 [-init, init] 范围内均匀地随机选择 Θ(l) 的值。
你应该使用 init = 0.12这个取值范围可以确保参数保持在较小的范围内,并提高学习效率。你的任务是完成 randInitializeWeights.m 来初始化 Θ 的权重;修改该文件并填写以下代码:
在这里插入图片描述

def random_init(size):
    '''从服从的均匀分布的范围中随机返回size大小的值'''
    return np.random.uniform(-0.12, 0.12, size)

2.3 反向传播

在这里插入图片描述
现在,你将实现反向传播算法。回顾一下:
反向传播算法的原理如下。给定一个训练示例(x(t), y(t)),我们将首先运行 “前向传递”,计算整个网络的所有激活,包括假设 hΘ(x) 的输出值。然后,对于第 l 层的每个节点 j,我们要计算一个 "误差项 "δ (l)j,以衡量该节点对输出中的任何误差 "负责 "的程度。对于输出节点,我们可以直接测量网络激活与真实目标值之间的差值,并用它来定义δ (3)j(因为第 3 层是输出层)。对于隐藏单元,您将根据第 (l + 1) 层节点误差项的加权平均值来计算 δ(l)j。您应该在一个每次处理一个示例的循环中实现步骤 1 至 4。具体来说,您应该为 t = 1:m 实现一个 for 循环,并将下面的 1-4 步放在 for 循环中,第 t 次迭代对第 t 个训练示例(x(t), y(t))进行计算。步骤 5 将累积梯度除以 m,得到神经网络成本函数的梯度。

  1. 将输入层的值(a(1))设置为第 t 个训练示例 x(t)。执行前馈传递(图 2),计算第 2 层和第 3 层的激活度(z(2), a(2), z(3), a(3))。请注意,您需要添加一个 +1 项,以确保层 a (1) 和 a (2) 的激活向量也包括偏置单元。在 Octave/MATLAB 中,如果 a 1 是一个列向量,则加 1 相当于 a 1 = [1 ; a 1]。
  2. 对于第 3 层(输出层)的每个输出单元 k,设置
    在这里插入图片描述
  3. 对于隐层 l = 2,设置
    在这里插入图片描述
  4. 使用以下公式计算本例中的梯度。在 Octave/MATLAB 中,删除 δ 相当于 delta 2 = delta 2(2:end)在这里插入图片描述
  5. 将累积梯度除以 1/m,得到神经网络成本函数的(非正规化)梯度在这里插入图片描述
print('a1', a1.shape, 't1', t1.shape)
print('z2', z2.shape)
print('a2', a2.shape, 't2', t2.shape)
print('z3', z3.shape)
print('a3', h.shape)
'''
a1:输入层的激活值(包括偏置项)。形状为 (5000, 401),表示有5000个样本,每个样本有401个特征(包括偏置项)。
t1:第一个隐藏层的权重矩阵。形状为 (25, 401),表示第一个隐藏层有25个神经元,每个神经元有401个输入(包括偏置项)。
z2:第一个隐藏层的加权输入值。形状为 (5000, 25),表示5000个样本,每个样本有25个加权输入值。
a2:第一个隐藏层的激活值(包括偏置项)。形状为 (5000, 26),表示5000个样本,每个样本有26个激活值(包括偏置项)。
t2:输出层的权重矩阵。形状为 (10, 26),表示输出层有10个神经元,每个神经元有26个输入(包括偏置项)。
z3:输出层的加权输入值。形状为 (5000, 10),表示5000个样本,每个样本有10个加权输入值。
a3 (h):输出层的激活值(预测输出)。形状为 (5000, 10),表示5000个样本,每个样本有10个预测输出。
'''
def gradient(theta, X, y):
    '''
    unregularized gradient, notice no d1 since the input layer has no error 
    return 所有参数theta的梯度,故梯度D(i)和参数theta(i)同shape,重要。
    '''
    
    # 反序列化 theta 为两个参数矩阵 t1 和 t2
    t1, t2 = deserialize(theta)  # 将参数向量theta分解为t1和t2

    # 使用前向传播函数计算每层的激活值和加权输入
    a1, z2, a2, z3, h = feed_forward(theta, X)  # 前向传播,计算激活值和加权输入
    
    # 计算输出层的误差
    d3 = h - y  # (5000, 10)  # 计算输出层误差,预测输出与实际标签之差
    
    # 计算第一个隐藏层的误差,忽略偏置项
    d2 = d3 @ t2[:,1:] * sigmoid_gradient(z2)  # (5000, 25)  # 计算第一个隐藏层误差
    
    # 计算输出层的梯度
    D2 = d3.T @ a2  # (10, 26)  # 计算输出层的梯度
    
    # 计算第一个隐藏层的梯度
    D1 = d2.T @ a1  # (25, 401)  # 计算第一个隐藏层的梯度
    
    # 将两个梯度矩阵序列化为一个向量
    D = (1 / len(X)) * serialize(D1, D2)  # (10285,)  # 将梯度矩阵序列化为向量,并按样本数量平均
    return D  # 返回梯度向量

2.4梯度检测

在你的神经网络中,你正在最小化成本函数 J(Θ)。要对参数进行梯度检查,可以想象将参数 Θ(1)、Θ(2) "展开 "成一个长向量 θ。
假设你有一个函数 fi(θ),声称可以计算 ∂/∂θi J(θ);你想检查 fi 是否输出了正确的导数值。
在这里插入图片描述

因此,θ(i+) 与 θ 相同,只是第 i 个元素增加了 。类似地,θ(i-)是第 i 个元素减少了 。现在可以用数字验证 fi(θ) 的正确性,方法是对每 i 个元素进行检验:
在这里插入图片描述
这两个值的近似程度取决于 J 的细节。不过,假设 = 10-4,你通常会发现上面左侧和右侧的值至少会相差 4 个有效数字(通常还会更多)。
我们已在 computeNumericalGradient.m 中为您实现了计算数值梯度的函数。虽然您无需修改该文件,但我们强烈建议您查看代码以了解其工作原理。在 ex4.m 的下一步,它将运行所提供的函数 checkNNGradients.m,该函数将创建一个小型神经网络和数据集,用于检查您的梯度。如果您的反向传播实现是正确的,您应该看到相对差异小于 1e-9。

def gradient_checking(theta, X, y, e):
    def a_numeric_grad(plus, minus):
        """
        对每个参数theta_i计算数值梯度,即理论梯度。
        """
        # 计算正则化损失的数值梯度
        return (regularized_cost(plus, X, y) - regularized_cost(minus, X, y)) / (e * 2)
   
    numeric_grad = [] 
    for i in range(len(theta)):
        plus = theta.copy()  # 深拷贝,否则会改变原始的theta
        minus = theta.copy()
        plus[i] = plus[i] + e  # 在theta的第i个参数上加e
        minus[i] = minus[i] - e  # 在theta的第i个参数上减e
        grad_i = a_numeric_grad(plus, minus)  # 计算数值梯度
        numeric_grad.append(grad_i)  # 将计算得到的梯度添加到列表中
    
    numeric_grad = np.array(numeric_grad)  # 将梯度列表转换为NumPy数组
    analytic_grad = regularized_gradient(theta, X, y)  # 计算解析梯度(通过反向传播)
    diff = np.linalg.norm(numeric_grad - analytic_grad) / np.linalg.norm(numeric_grad + analytic_grad)  # 计算数值梯度和解析梯度的相对误差

    print('If your backpropagation implementation is correct,\nthe relative difference will be smaller than 10e-9 (assume epsilon=0.0001).\nRelative Difference: {}\n'.format(diff))

2.5 正则化神经网络

成功实施反向传播算法后,您将在梯度中加入正则化。具体来说,在使用反向传播算法计算出 ∆(l) ij 后,应使用以下方法添加正则化值
在这里插入图片描述
请注意,您不应对 Θ(l) 的第一列进行正则化,因为该列用于偏置项。此外,在参数 Θ(l)ij 中,i 的索引 从 1 开始,j 的索引从 0 开始
在这里插入图片描述

def regularized_gradient(theta, X, y, l=1):
    """不惩罚偏置单元的参数"""
    # 使用 feed_forward 函数进行前向传播,计算激活值和加权输入值
    a1, z2, a2, z3, h = feed_forward(theta, X)
    
    # 使用 gradient 函数计算梯度,使用 deserialize 函数将其反序列化为 D1 和 D2
    D1, D2 = deserialize(gradient(theta, X, y))
    
    # 将 t1 和 t2 的偏置单元部分(第 0 列)设为 0,这样在正则化时不包含偏置单元的参数
    t1[:,0] = 0
    t2[:,0] = 0
    
    # 计算正则化的梯度,加入正则化项,正则化参数 l 默认为 1
    reg_D1 = D1 + (l / len(X)) * t1
    reg_D2 = D2 + (l / len(X)) * t2
    
    # 使用 serialize 函数将 reg_D1 和 reg_D2 序列化,并返回
    return serialize(reg_D1, reg_D2)

2.6 优化参数

在成功实现神经网络代价函数和梯度计算后,ex4.m 脚本的下一步将使用 fmincg 来学习一组好的参数。训练完成后,ex4.m 脚本将通过计算正确示例的百分比来报告分类器的训练准确率。如果您的实现是正确的,那么报告的训练准确率应该在 95.3% 左右(由于随机初始化,准确率可能会有 1% 左右的变化)。通过对神经网络进行更多次的迭代训练,可以获得更高的训练精度。我们建议您尝试对神经网络进行更多迭代训练(例如,将 MaxIter 设置为 400),并改变正则化参数 λ。

def nn_training(X, y):
    init_theta = random_init(10285)  # 初始化权重,维度为 10285(25*401 + 10*26)
    
    res = opt.minimize(fun=regularized_cost,  # 目标函数是正则化的损失函数
                       x0=init_theta,  # 初始权重
                       args=(X, y, 1),  # 传递给目标函数的参数:输入数据、标签数据和正则化参数
                       method='TNC',  # 使用信赖域牛顿共轭梯度法
                       jac=regularized_gradient,  # 梯度函数是正则化的梯度
                       options={'maxiter': 400})  # 最大迭代次数为 400
    return res  # 返回优化结果

def accuracy(theta, X, y):
    _, _, _, _, h = feed_forward(theta, X)  # 进行前向传播,计算输出层激活值(预测值)
    y_pred = np.argmax(h, axis=1) + 1  # 找到每行最大值的索引,表示预测的分类标签(索引加1)
    print(classification_report(y, y_pred))  # 打印分类报告,包括精确度、召回率和F1-score等指标

3.可视化隐藏层

了解神经网络学习内容的一种方法是直观地观察隐藏单元捕捉到的表征。非正式地说,给定一个特定的隐藏单元,可视化其计算结果的一种方法是找到一个能使其激活的输入 x(即激活值 (a(l)i) 接近 1)。对于您训练的神经网络,请注意 Θ(1) 的第 i 行是一个 401 维的向量,代表第 i 个神经网络的参数。
隐藏单元。如果我们舍弃偏置项,就会得到一个 400 维的向量,表示从每个输入像素到隐藏单元的权重。因此,直观显示隐藏单元捕捉到的 "表示 "的一种方法是将这个 400 维向量重塑为 20 × 20 的图像并显示出来3。ex4.m 的下一步是使用 displayData 函数来实现这一功能,它将向您显示一幅包含 25 个单元的图像(与图 4 类似),每个单元对应网络中的一个隐藏单元。
在这里插入图片描述

def plot_hidden(theta):
    t1, _ = deserialize(theta)  # 反序列化 theta,得到权重矩阵 t1 和 t2(这里只关心 t1)
    t1 = t1[:, 1:]  # 去掉 t1 的偏置单元部分(第 0 列)
    
    fig, ax_array = plt.subplots(5, 5, sharex=True, sharey=True, figsize=(6,6))  # 创建一个 5x5 的子图网格,图像大小为 6x6
    
    for r in range(5):  # 遍历每一行
        for c in range(5):  # 遍历每一列
            ax_array[r, c].matshow(t1[r * 5 + c].reshape(20, 20), cmap='gray_r')  # 将每个隐藏层神经元的权重可视化为 20x20 的图像
            plt.xticks([])  # 去掉 x 轴刻度
            plt.yticks([])  # 去掉 y 轴刻度
    
    plt.show()  # 显示图像

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1859855.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Steam怎么卸载DLC Steam怎么只卸载DLC不卸载游戏教程

我们玩家在steam中玩游戏,有一个功能特别重要,那就是DLC,其实也就是一款游戏的扩展,很多游戏都有DLC,让游戏玩法特别丰富,比如都市天际线的DLC,给城市中就增加了很多建筑,或者更便捷…

第十二次作业

成功做出insert 点击新增跳转到insert.html 点击增加,跳转回studentinformation2.html 数据表和页面都显示出新增的数据了 成功做出来删除 点击删除按钮 点击确定,丽丽被成功删除! 一些代码

【Linux】进程间通信_2

文章目录 七、进程间通信1. 进程间通信分类管道 未完待续 七、进程间通信 1. 进程间通信分类 管道 管道的四种情况: ①管道内部没有数据,并且具有写端的进程没有关闭写端,读端就要阻塞等待,知道管道pipe内部有数据。 ②管道内部…

混合云管道的未来:集成 MinIO、Tailscale 和 GitHub Actions

数据处理是现代软件开发的基本实践。它使团队能够自动收集、处理和存储数据,确保高质量的数据和高效的处理。 在本文中,我们将探讨如何建立一个全面的数据处理管道,重点介绍如何使用 Tailscale GitHub Action 进行安全网络。此设置还将包含 …

MindManager2024思维导图大升级!轻松绘制思维导图

思维导图大升级!MindManager2024新体验 最近在用MindManager2024制作思维导图,感觉它是一款非常专业的软件。它的界面设计简洁明了,操作流畅,让我能够轻松地整理思绪、规划计划和记录灵感💡。 MindManager思维导图工具…

电商平台是申请ICP许可证还是EDI许可证?

随着直播行业大火热,越来越多的企业开始从事电商业务,那么电商平台的,需要办理什么许可证?是ICP许可证还是EDI许可证?今天小编为您详细说明一下。 首先,不管是ICP许可证还是EDI许可证,都属于增…

写一个坏越的个人天地(三)

昨天卡巴卡巴还是投出了学习代码以来的第一份简历,遇到好的岗位还是想争取下的吧,虽然我觉得大概率还是gg了。 昨天完成了首页的上半部分 下半部分我的构思是左右栏,左侧为菜单栏,右侧为业务栏,左侧调整右侧router进行切换内容 可以用来展示js css的小demo 稍微调整下ro…

ONLYOFFICE8.1版本震撼来袭

目录 软件简介 产品概述: 功能特点: 技术原理: 版本与部署: 8.1版本更新 全新的PDF编辑器 1.文本编辑 2.页面处理 (添加、旋转、删除) 3.插入和调整各种对象,例如表格、形状、文本框、…

Redis之商品缓存

文章目录 什么是缓存添加Redis缓存缓存更新策略缓存穿透缓存空对象布隆过滤器 缓存雪崩给不同的key的TTL添加随机值利用Redis集群提高服务的可用性给缓存业务添加降级限流策略给业务添加多级缓存 缓存击穿互斥锁逻辑过期 缓存工具封装方法1 写入redis方法2 设置逻辑过期方法3 解…

Android集成高德地图SDK(1)

1.新建Android应用,确定应用包名 2.注册高德开放平台,打开控制台页面,应用管理,我的应用,创建新应用 3.添加Key 4.获取SHA1码 找到Android Studio自带的keytool 将其拖到cmd中,输入命令 -v -list -keystor…

Qt:2.环境搭建

目录 1.搭建需要的三个组件: 2.下载Qt安装包: 3.安装qt: 4.配置环境变量: 1.搭建需要的三个组件: C编译器(gcc,cl.exe等)Qt的SDK:软件开发工具包,Windows…

component-切换选中状态更改

1.例 实现默认选中初始值&#xff0c;点击选中对应状态。 2.代码 2.1 html <span click"ponIn()" class"market-switch" :style"{color: SelectedOne ? :#1890FF,borderBottom:SelectedOne ? :1px solid #1890FF}">业务1</span>…

适用于 Windows 11 的 5 大数据恢复软件 [免费和付费]

为什么我们需要Windows 11数据恢复软件&#xff1f; 计算机用户经常遇到的一件事就是数据丢失&#xff0c;这种情况随时可能发生。错误地删除重要文件和文件夹可能会非常令人担忧&#xff0c;但幸运的是&#xff0c;有一种方法可以恢复 PC 上丢失的数据。本文将向您展示可用于…

Servlet工作原理

Servlet 工作原理 编写Servlet 创建servlet 创建一个MyServlet继承HttpServlet&#xff0c;重写doGet和doPost方法&#xff0c;也就是看请求的方式是get还是post&#xff0c;然后用不同的处理方式来处理请求&#xff0c; 2. 配置Servlet //添加参数 <servlet><se…

【C++/STL】:优先级队列(priority_queue)的使用及底层剖析仿函数

目录 &#x1f4a1;前言一&#xff0c;优先级队列的使用二&#xff0c;仿函数1&#xff0c;什么是仿函数2&#xff0c;仿函数的简单示例 三&#xff0c;优先级队列的底层剖析 &#x1f4a1;前言 优先队列(priority_queue)是一种容器适配器&#xff0c;默认使用vector作为其底层…

小学数学蝴蝶模型详解

蝴蝶模型 1.蝴蝶模型仅存在于梯形中&#xff0c;是连接梯形两条对角线而形成的&#xff0c;如下图&#xff1a; 2.蝴蝶模型有几条公式 (1) (2) S△AODS△BOC 等等......

GPT-5的未来愿景:技术突破、智能协作与伦理道德考量

随着人工智能技术日新月异的进步&#xff0c;GPT-5已然崭露头角&#xff0c;它不仅预示着新一轮的技术风暴&#xff0c;更象征着自然语言处理与智能系统协作将迈入一个崭新的纪元。然而&#xff0c;在这一技术奇迹的背后&#xff0c;我们亦需审慎思考伦理道德及安全性问题。 技…

ChatGPT的原理简介

目录 前言 1. 什么是ChatGPT&#xff1f; 2. GPT模型的基本原理 自注意力机制 预训练和微调 3. ChatGPT的工作流程 4. ChatGPT的优势和挑战 5. 实例对话 6. 未来展望 结语 前言 在这个智能科技飞速发展的时代&#xff0c;聊天机器人逐渐成为我们生活中的“新朋友”。…

Go的GUI Fyne开发环境搭建—Windows 11

安装go 到官网下载安装go安装包 https://go.dev/learn/ 通过如下命令检验安装是否成功&#xff0c;出现版本号则安装成功 go version安装国内go依赖包代理 go env -w GOPROXYhttps://goproxy.cn安装gcc编译器 直接用官网提供的安装建议第二条&#xff0c;到这个地址进行下载…

mysql数据库索引的选择性

文章目录 索引的选择性索引选择性的计算单列索引的选择性计算值组合列索引的选择性计算值 索引列的两个基本要求 索引的选择性 是指不重复的索引值与表总记录数的比值&#xff0c;其范围(0,1]。通过索引的选择性&#xff0c;可以确定该索引是否合理(70%)。索引选择性的计算 表…