“理解梯度下降:直觉、数学公式和推导”

news2024/11/29 13:28:29


一、说明

         梯度下降是机器学习中使用的一种流行的优化算法,通过迭代调整函数的参数来最小化函数。基本思想是将函数的参数沿函数梯度最陡峭下降的方向移动。

二、关于梯度的叙述

        简单来说,想象一下你在山顶,你想尽快到达山脚下。你可以开始下坡,朝着感觉最陡的方向走几步。但是,您可能无法始终分辨出哪个方向真正最陡峭,尤其是在地形复杂的情况下。

        相反,您可以使用一个工具来测量各个方向的地形陡度,例如指向下坡的指南针。使用此工具,您可以沿着指南针感觉最陡的方向迈出一小步,直到到达底部。梯度下降就像机器学习模型的指南针:它告诉模型如何调整其参数以最小化它试图优化的功能。

        具体来说,梯度下降通过计算函数在当前点的梯度来工作,该梯度表示最陡峭的上升方向。然后,该算法朝着相反的方向迈出一小步,朝着最陡峭的下降方向迈出。这个过程重复了很多次,每一步的大小由学习率决定,直到算法达到最小值,因为我们的步长(学习率)正在减少。最初,我们的步长很高。

        在机器学习中,正在优化的函数通常是一个成本函数,用于衡量模型在给定任务上的表现。通过使用梯度下降来最小化此成本函数,模型可以随着时间的推移提高其性能,学习做出更好的预测或分类。

        以下是使用梯度下降在简单线性回归中查找 b 值的逐步数学公式和推导,假设我们已经有了 m 的值:

简单线性回归的方程是 y = mx + b,其中 y 是因变量,x 是自变量,m 是直线的斜率,b 是 y 截距。

假设我们有一组 n 个数据点 (x1, y1), (x2, y2), ..., (xn, yn),我们想找到最小化平方误差 (SSE) 之和的 m 和 b 值:

SSE = Σ(yi — (mx_i + b))², i = 1 到 n

要使用梯度下降找到 b 的值,我们首先需要计算 SSE 相对于 b 的偏导数:

∂SSE/∂b = Σ-2(yi — (mx_i + b))

接下来,我们使用梯度下降更新规则更新 b 的值:

b_new = b — alpha * ∂SSE/∂b

其中阿尔法是学习率。我们重复这个过程,直到b的值收敛到最小值。

三、梯度如何实现

3.1 逐步推导:

  1. 将 b 初始化为随机值。
  2. 计算上证相对于b的梯度:
  3. ∂SSE/∂b = Σ-2(yi — (mx_i + b))
  4. 使用梯度下降更新规则更新 b:
  5. b_new = b — alpha * ∂SSE/∂b
  6. 重复步骤 2 和 3,直到 b 的值收敛到最小值。

3.2 下面是一个使用梯度下降查找 b 值的 Python 代码示例:

from sklearn.datasets import make_regression
import numpy as np
X,y = make_regression(n_samples=4, n_features=1, n_informative=1, n_targets=1,noise=80,random_state=13)
import matplotlib.pyplot as plt
plt.scatter(X,y)

绘制散点图

# Lets apply OLS
from sklearn.linear_model import LinearRegression
reg = LinearRegression()
reg.fit(X,y)
     
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)
reg.coef_
     
>>>>>> array([78.35063668])
reg.intercept_
     
>>>>> 26.15963284313262
plt.scatter(X,y)
plt.plot(X,reg.predict(X),color='red')reg = LinearRegression()
reg.fit(X,y)
     
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)
reg.coef_
     
>>>>>> array([78.35063668])
reg.intercept_
     
>>>>> 26.15963284313262
plt.scatter(X,y)
plt.plot(X,reg.predict(X),color='red')

通过OLS方法进行线预测。

# Lets apply Gradient Descent assuming slope is constant m = 78.35
# and let's assume the starting value for intercept b = 0
y_pred = ((78.35 * X) + 100).reshape(4)
plt.scatter(X,y)
plt.plot(X,reg.predict(X),color='red',label='OLS')
plt.plot(X,y_pred,color='#00a65a',label='b = 0')
plt.legend()
plt.show()

m = 78.35
b = 100
loss_slope = -2 * np.sum(y - m*X.ravel() - b)
loss_slope
     
>>>> 590.7223659179078
# Lets take learning rate = 0.1
lr = 0.1
step_size = loss_slope*lr
step_size
     
>>>>> 59.072236591790784
# Calculating the new intercept
b = b - step_size
b
     
>>>> 40.927763408209216
y_pred1 = ((78.35 * X) + b).reshape(4)
plt.scatter(X,y)
plt.plot(X,reg.predict(X),color='red',label='OLS')
plt.plot(X,y_pred1,color='#00a65a',label='b = {}'.format(b))
plt.plot(X,y_pred,color='#A3E4D7',label='b = 0')
plt.legend()
plt.show()

Comparison different values of b

# Iteration 2
loss_slope = -2 * np.sum(y - m*X.ravel() - b)
loss_slope
     
>>>>> 118.14447318358157
step_size = loss_slope*lr
step_size
     
>>>>> 11.814447318358157
b = b - step_size
b
     
>>>>> 29.11331608985106
y_pred2 = ((78.35 * X) + b).reshape(4)
plt.scatter(X,y)
plt.plot(X,reg.predict(X),color='red',label='OLS')
plt.plot(X,y_pred2,color='#00a65a',label='b = {}'.format(b))
plt.plot(X,y_pred1,color='#A3E4D7',label='b = {}'.format(b))
plt.plot(X,y_pred,color='#A3E4D7',label='b = 0')
plt.legend()
plt.show()

loss_slope = -2 * np.sum(y - m*X.ravel() - b)
loss_slope
     
>>>> 23.62889463671634
step_size = loss_slope*lr
step_size
     
>>>> 2.362889463671634
b = b - step_size
b
     
>>>> 26.750426626179426
y_pred3 = ((78.35 * X) + b).reshape(4)
plt.figure(figsize=(15,15))
plt.scatter(X,y)
plt.plot(X,reg.predict(X),color='red',label='OLS')
plt.plot(X,y_pred3,color='#00a65a',label='b = {}'.format(b))
plt.plot(X,y_pred2,color='#A3E4D7',label='b = {}'.format(b))
plt.plot(X,y_pred1,color='#A3E4D7',label='b = {}'.format(b))
plt.plot(X,y_pred,color='#A3E4D7',label='b = 0')
plt.legend()
plt.show()

b = -100
m = 78.35
lr = 0.01
epochs = 100
for i in range(epochs):
  loss_slope = -2 * np.sum(y - m*X.ravel() - b)
  b = b - (lr * loss_slope)
  y_pred = m * X + b
  plt.plot(X,y_pred)
plt.scatter(X,y)

四、“可视化梯度下降:查找 y 截距的分步示例。”

4.1 最佳贴合线:

当我们已经有斜率时试图找到 b(截距)

4.2 该图说明了周期数与损失之间的关系。

损失与时期(红色标记→学习率)

损失与时期

该图说明了 epoch 数与损失之间的关系,同时还指示了优化算法中使用的学习率。随着 epoch 数量的增加,损失会减少,这表明模型正在学习并提高其在任务上的性能。但是,重要的是要注意,在整个训练过程中,学习率并不是恒定的。

在训练开始时,学习率很高,这使得模型能够对其参数进行大量更新,并迅速收敛到损失函数的最小值。当模型接近最小值时,学习率会降低,以避免超过最小值并确保更稳定的收敛。

4.3 学习率。

学习率是一个超参数,用于控制梯度下降算法每次迭代中执行的步骤的大小。如果学习率太低,算法可能会收敛缓慢,而如果学习率太高,算法可能会超过最小值并发散。

以下是不同学习率如何影响梯度下降的图表表示:

在图中,我们有一个简单的 2D 成本函数,只有一个最小值。蓝点代表数据点,蓝线是我们具有不同学习率的梯度下降算法的最佳拟合线。

在左边,我们的学习率很低。该算法沿梯度方向采取小步骤,并缓慢收敛到最小值。

在中间,我们的学习率适中。该算法采用更大的步骤,并更快地收敛到最小。

在右边,我们的学习率很高。该算法采取非常大的步骤并超过最小值,导致算法在最小值附近发散和振荡。

为手头的特定问题选择合适的学习率很重要,因为不同的问题可能有不同的最佳学习率。一种常见的方法是尝试不同的学习率并观察算法的收敛行为。

减少损失:优化学习率 |机器学习 |谷歌开发者

4.4 逐步数学公式和推导,用于使用梯度下降在简单线性回归中查找 m 和 b 的值:

简单线性回归的方程是 y = mx + b,其中 y 是因变量,x 是自变量,m 是直线的斜率,b 是 y 截距。

假设我们有一组 n 个数据点 (x1, y1), (x2, y2), ..., (xn, yn),我们想找到最小化平方误差 (SSE) 之和的 m 和 b 值:

SSE = Σ(yi — (mx_i + b))², i = 1 到 n

要使用梯度下降找到 m 和 b 的值,我们需要计算 SSE 相对于 m 和 b 的偏导数:

∂SSE/∂m = Σ-2x_i(yi — (mx_i + b))

∂SSE/∂b = Σ-2(yi — (mx_i + b))

接下来,我们使用梯度下降更新规则更新 m 和 b 的值:

m_new = m — alpha * ∂SSE/∂m

b_new = b — alpha * ∂SSE/∂b

其中阿尔法是学习率。我们重复此过程,直到 m 和 b 的值收敛到最小值。

这是逐步推导:

  1. 将 m 和 b 初始化为随机值。
  2. 计算SSE相对于m和b的梯度:
  3. ∂SSE/∂m = Σ-2x_i(yi — (mx_i + b))
  4. ∂SSE/∂b = Σ-2(yi — (mx_i + b))
  5. 使用梯度下降更新规则更新 m 和 b:
  6. m_new = m — alpha * ∂SSE/∂m
  7. b_new = b — alpha * ∂SSE/∂b
  8. 重复步骤 2 和 3,直到 m 和 b 的值收敛到最小值。

下面是一个使用梯度下降查找 m 和 b 值的 Python 代码示例:

from sklearn.datasets import make_regression
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import cross_val_score
X,y = make_regression(n_samples=100, n_features=1, n_informative=1, n_targets=1,noise=20,random_state=13)
plt.scatter(X,y)

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=2)
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_train,y_train)
print(lr.coef_)
print(lr.intercept_)
>>>> [28.12597332]
>>>>-2.271014426178382
y_pred = lr.predict(X_test)
from sklearn.metrics import r2_score
r2_score(y_test,y_pred)
>>>> 0.6345158782661013
class GDRegressor:
    
    def __init__(self,learning_rate,epochs):
        self.m = 100
        self.b = -120
        self.lr = learning_rate
        self.epochs = epochs
        
    def fit(self,X,y):
        # calcualte the b using GD
        for i in range(self.epochs):
            loss_slope_b = -2 * np.sum(y - self.m*X.ravel() - self.b)
            loss_slope_m = -2 * np.sum((y - self.m*X.ravel() - self.b)*X.ravel())
            
            self.b = self.b - (self.lr * loss_slope_b)
            self.m = self.m - (self.lr * loss_slope_m)
        print(self.m,self.b)
        
    def predict(self,X):
        return self.m * X + self.b
    
gd = GDRegressor(0.001,50)
gd.fit(X_train,y_train)
>>>> 28.159367347119066 -2.3004574196824854
y_pred = gd.predict(X_test)
from sklearn.metrics import r2_score
r2_score(y_test,y_pred)
>>>>> 0.6343842836315579

4.5 “收敛和可视化:使用梯度下降找到最佳拟合线”

在此可视化中,谷的“暗面”表示损失函数的最小点,其中模型参数经过优化以产生最佳预测。等值线图的形状可以根据模型的复杂性和要优化的参数数量而变化。

3D 表示

在这里,我们尝试用多元线性回归来表述。

五、多元线性回归模型定义为 

y = β0 + β1x1 + β2x2 + ... + βnxn

其中 β0, β1, β2, ..., βn 是我们想要优化的模型的系数(也称为权重或参数)。

5.1 为了找到β0,β1,β2,...,βn的最佳值,我们使用批量梯度下降,它涉及以下步骤:

注意:批量梯度下降与梯度下降上的内容没有什么不同

  1. 初始化:我们从系数的一些初始值开始,比如β0 = 0,β1 = 0,β2 = 0,...,βn = 0。
  2. 计算成本函数:我们计算成本函数 J(β),用于衡量模型与数据的拟合优度。成本函数通常定义为均方误差 (MSE),它是预测值与输出变量 y 的实际值之间的平方差的平均值。
  3. 计算梯度:我们计算成本函数相对于系数 β0、β1、β2、...、βn 的梯度。梯度是 n+1 个元素的向量,其中第一个元素对应于 β0,其余元素对应于 β1、β2、...、βn。
  4. 更新系数:我们使用梯度下降更新规则更新系数:

βj := βj — α * ∂J(β) / ∂βj

其中α是学习率(控制更新大小的超参数),j = 0, 1, 2, ..., n。

  1. 重复步骤 2-4 直到收敛:我们重复步骤 2-4,直到成本函数收敛(即停止显着下降)。

5.2 下面是如何将批量梯度下降应用于高维多元线性回归问题的示例:

假设我们有一个数据集,其中包含 n = 10 个特征和 m = 1000 个观测值。目标是根据平方英尺、卧室数量、浴室数量等特征预测房屋价格。

我们可以将数据集表示为 m x (n+1) 矩阵 X,其中 X 的第一列是 1 的向量(对于截距项),其余列表示 n 个特征。我们还有一个m元素的向量y,它代表房屋的实际价格。

我们可以将系数 β0, β1, β2, ..., βn 初始化为零,并设置一个学习率α(例如,0.01)。然后,我们可以将成本函数 J(β) 计算为:

J(β) = 1/2m * sum((Xβ — y)²)

其中 Xβ 是基于β系数的当前值预测的房屋价格,并且对所有 m 个观测值求和。

然后,我们可以将成本函数的梯度计算为:

∂J(β) / ∂βj = 1/m * sum((Xβ — y) * Xj)

其中 Xj 是矩阵 X 的第 j 列,总和被接管

继续 aove

所有 m 观测值。

使用梯度下降更新规则,我们可以将系数更新为:

βj := βj — α * ∂J(β) / ∂βj

对于 j = 0, 1, 2, ..., n。此更新规则实质上将系数沿成本函数最陡下降的方向移动,直到达到最小值。

我们可以重复计算成本函数和梯度,以及系数的更新,直到成本函数收敛(即停止显着下降)。一旦系数收敛,我们就有了最适合数据的最优值β0,β1,β2,...,βn。

批量梯度下降的优点是能够收敛到成本函数的全局最小值,但对于大型数据集,它的计算成本可能很高。还有其他优化算法,例如随机梯度下降和小批量梯度下降,对于大型数据集可以更有效。

六、python代码

from sklearn.datasets import load_diabetes
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
X,y = load_diabetes(return_X_y=True)
print(X.shape)
print(y.shape)
>>>> (442, 10)
>>>>> (442,)
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=2)
reg = LinearRegression()
reg.fit(X_train,y_train)
LinearRegression()
print(reg.coef_)
print(reg.intercept_)
>>>> [  -9.16088483 -205.46225988  516.68462383  340.62734108 -895.54360867
       561.21453306  153.88478595  126.73431596  861.12139955   52.41982836]
>>>> 151.88334520854633
y_pred = reg.predict(X_test)
r2_score(y_test,y_pred)
>>>>> 0.4399387660024645
X_train.shape
>>>>>> (353, 10)
class GDRegressor:
    
    def __init__(self,learning_rate=0.01,epochs=100):
        
        self.coef_ = None
        self.intercept_ = None
        self.lr = learning_rate
        self.epochs = epochs
        
    def fit(self,X_train,y_train):
        # init your coefs
        self.intercept_ = 0
        self.coef_ = np.ones(X_train.shape[1])
        
        for i in range(self.epochs):
            # update all the coef and the intercept
            y_hat = np.dot(X_train,self.coef_) + self.intercept_
            #print("Shape of y_hat",y_hat.shape)
            intercept_der = -2 * np.mean(y_train - y_hat)
            self.intercept_ = self.intercept_ - (self.lr * intercept_der)
            
            coef_der = -2 * np.dot((y_train - y_hat),X_train)/X_train.shape[0]
            self.coef_ = self.coef_ - (self.lr * coef_der)
        
        print(self.intercept_,self.coef_)
    
    def predict(self,X_test):
        return np.dot(X_test,self.coef_) + self.intercept_
gdr = GDRegressor(epochs=1000,learning_rate=0.5)
gdr.fit(X_train,y_train)
>>>>> 152.0135263267291 [  14.38915082 -173.72674118  491.54504015  323.91983579  -39.32680194
>>>>>  -116.01099114 -194.04229501  103.38216641  451.63385893   97.57119174]
y_pred = gdr.predict(X_test)
r2_score(y_test,y_pred)
>>>>> 0.4534524671450598

梯度下降也称为批量梯度下降。

        以下是批量梯度下降 (BGD)、随机梯度下降 (SGD) 和小批量梯度下降 (MBGD) 收敛性的更详细比较:

        BGD:

  • 计算成本函数在整个训练集上的梯度。
  • 每次迭代更新一次模型参数。
  • 收敛速度较慢但稳定地接近成本函数的最小值。
  • 可能比 SGD 和 MBGD 更稳定,但可能需要更长的时间才能收敛。
  • 需要比 SGD 和 MBGD 更多的内存和计算资源。

“理解梯度下降:直觉、数学公式和推导”

批次梯度下降

阿贾梅塔

七、BGD:

  • 计算成本函数在单个训练样本上的梯度。
  • 每个示例更新一次模型参数。
  • 收敛速度更快,但振荡更多,接近成本函数的最小值。
  • 可以对学习率的选择和数据随机性更敏感。
  • 比 BGD 需要更少的内存和计算资源。

随机梯度下降

SGD 代表 随机梯度下降。它是一种优化算法,用于最小化...

八、MBGD:

  • 计算成本函数在训练数据的小随机子集(小批次)上的梯度。
  • 每个小批量更新一次模型参数。
  • 在 SGD 的速度和 BGD 的稳定性之间提供折衷。
  • 收敛速度快于BGD,振荡比SGD小。
  • 需要的内存和计算资源比 BGD 少,但比 SGD 多。

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

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

相关文章

流程图规范

文章目录 1.符号概览2.要求2.1 从上至下,从左至右的流向顺序2.2 开始符号只能有一个出口2.3 进程符号不做逻辑校验2.4 相同流程图,符号大小应为一致2.5 引用流程,而不是重复绘制2.6 路径符号应尽量避免相互交叉2.7 同一路径,箭头只…

【Python】Python语言基础(下)

目录 第十一章 控制结构 for语句 if语句 while语句 第十二章 函数 函数介绍 函数的定义 函数的调用 函数的传参 函数的传参方式 位置实参 关键字实参 默认值实参 函数的返回值 函数传递未知数量的实参 函数的模块调用 调用整个模块 调用模块中特定功能 第十…

业财融合潮流下,构建国有企业全面预算管理体系

近年来,在我国快速发展的变革过程中,国有企业改革的持续深入需要积极结合市场环境和自身发展需求,然而其传统的财务管理模式难以适应企业提出的新要求,预算管理与经营销售之间不断出现隔阂。为确保全面预算管理在国有企业内部的良…

部署个人静态网站到阿里云服务器(含域名解析)

使用前提: 您目前已经有一个静态网站,可以在本地通过html进行访问。 1、购买阿里云服务器 该步骤最详细的教程来自官方文档 具体到从注册开始每一个鼠标点击都有图片介绍。 你可以按照他的步骤完成整个部署过程,当然可以自己选择服务器的…

【实用调试技巧】总是找不到Bug?手把手教你在vs2022中调试程序

🦄个人主页:修修修也 🎏所属专栏:程序调试及报错解决 ⚙️操作环境:Visual Studio 2022 目录 什么是Bug? 1947年9月9日:第一个"Bug"被发现 什么是调试? 调试是什么? 调试的基本步骤 Debug和Relese的区别 1.调试的区别 2.文件大小的…

13 | 如何正确使用 @Entity 里面的回调方法

Java Persistence API 里面规定的回调方法有哪些? JPA 协议里面规定,可以通过一些注解,为其监听回调事件、指定回调方法。下面我整理了一个回调事件注解表,分别列举了 PrePersist、PostPersist、PreRemove、PostRemove、PreUpdat…

线性排序:如何根据年龄给100万用户数据排序?

文章来源于极客时间前google工程师−王争专栏。 桶排序、计数排序、基数排序时间复杂度是O(n),所以这类排序算法叫作线性排序。 线性的原因:三个算法是非基于比较的排序算法,都不涉及元素之间的比较操作。 三种排序对排序的数据要求苛刻&am…

19 | 如何搞清楚事务、连接池的关系?正确配置是怎样的

事务的基本原理 在学习 Spring 的事务之前,你首先要了解数据库的事务原理,我们以 MySQL 5.7 为例,讲解一下数据库事务的基础知识。 我们都知道 当 MySQL 使用 InnoDB 数据库引擎的时候,数据库是对事务有支持的。而事务最主要的作…

(转)富文本编辑器——Vue2Editor

介绍 Vue2Editor是一个简单易用且功能强大的Vue版本的富文本编辑器,其基于Quill.js和Vuejs构建! 简单易用、功能强大的富文本编辑器——Vue2Editor Github https://github.com/davidroyer/vue2-editor 特性 简单易用;基于Vue.js & Quil…

【Golang】Go的并发和并行性解释。谁说Go不是并行语言?

偶然发现百度上有很多"师出同门"的"go是并发语言,而不是并行语言"的说法。让我顿感奇怪,"并行"说白了就是对CPU多核的利用,这年头不能利用多核的编译语言还有的混?而且还混的这么好?并且…

Linux网络编程系列之服务器编程——非阻塞IO模型

Linux网络编程系列 (够吃,管饱) 1、Linux网络编程系列之网络编程基础 2、Linux网络编程系列之TCP协议编程 3、Linux网络编程系列之UDP协议编程 4、Linux网络编程系列之UDP广播 5、Linux网络编程系列之UDP组播 6、Linux网络编程系列之服务器编…

echarts关于一次性绘制多个饼图 (基于vue3)

在echarts中,dataset 和 source 是用来配置数据的选项。 dataset 是一个包含数据相关配置的对象,用于指定数据的来源和格式。它可以包含多个维度的数据集,每个维度都可以有自己的名称和数据。 source 是 dataset 中的一个子项,用于…

图计算(林子雨慕课课程)

文章目录 13. 图计算13.1 图计算简介13.2 Pregel简介13.3 Pregel图计算模型13.3.1 有向图和顶点13.3.2 Pregel的计算过程13.3.2 Pregel实例 13.4 Pregel的C API13.4.1 定义Vertex基类13.4.2 消息传递机制和Combiner13.4.3 Aggregator、拓扑改变和输入输出 13.5 Pregel的体系结构…

【通过实验带你认识linux下的源码编译】

通过实验带你认识linux下的源码编译 01 初识项目编译02 编译过程03 完整的编译过程1、创建源代码文件2、创建configure脚本3、创建Makefile.am 源代码是相对目标代码和可执行代码而言的。源代码是用汇编语言和高级语言写出来的代码。 目标代码是指源代码经过编译程序产生的能被…

qml介绍

文章目录 qml简介对象一个风车的例子 qml简介 从 Qt 4.7 开始,Qt 引入了一种声明式脚本语言,称为 QML(Qt Meta Language 或者 Qt Modeling Language),作为 C 语言的一种替代。而 Qt Quick 就是使用 QML 构建的一套类库…

(latex中appendix附录怎么写)以及(附录里面的图片表格之类的如何重新编号)

文章目录 初级:怎么写进阶:怎么重新编号进阶:怎么换成单栏格式 初级:怎么写 这个很简单,我一开始以为很复杂。 \begin{document} #这里是“正文”。 #这里是“引用”。 #下面开始是附录。 \appendix \section{Proofs…

英语——分享篇——每日100词——801-900

medical——adj.医疗的——me我(熟词)di弟(拼音)cal擦了(拼音) chief——n.酋长——thief小偷——小偷拜见酋长 pork——n.猪肉——p皮鞋(编码)or偶人(拼音)k机关枪(编码)——穿着皮鞋的偶人扛着机关枪挑猪肉 pie——n.馅饼,派——瞥——他无意瞥见一块馅饼 saus…

GB28181平台简介

产品简介 LiveMedia视频中间件是支持部署到本地服务器或者云服务器的纯软件服务,也提供服务器、GPU一体机全包服务,提供视频设备管理、无插件、跨平台的实时视频、历史回放、语音对讲、设备控制等基础功能,支持视频协议有海康、大华私有协议…

Golang学习记录:基础篇练习(一)

Golang学习记录:基础篇练习(一) 1、九九乘法表2、水仙花数3、斐波那契数列4、编写一个函数,求100以内的质数5、统计字符串里面的字母、数字、空格以及其他字符的个数6、二维数组对角线的和7、冒泡排序算法8、选择排序算法9、二分查…

JDK 19 协程新特性学习

目录 一、协程定义 二、协程发展史 (一)协程的基本发展史说明 (二)Java协程发展说明 三、JDK 19 协程的原理细节 (一)Thread.ofVirtual().start() (二)SocketChannel.write(…