机器学习笔记之核函数再回首:Nadarya-Watson核回归python手写示例

机器学习笔记之核函数再回首——Nadaraya-Watson核回归手写示例

引言

本节从代码角度,介绍基于高维特征向量使用 Nadaraya-Watson \text{Nadaraya-Watson} Nadaraya-Watson核回归的示例。

回顾: Nadaraya-Watson \text{Nadaraya-Watson} Nadaraya-Watson核回归

在注意力机制基本介绍中,我们提到过这种基于注意力机制权重懒惰学习方法。该方法与注意力机制关联的核心操作有如下步骤:

通过核函数描述样本之间的关联关系

我们想要主观获取某陌生样本 x ∈ R p x \in \mathbb R^p xRp数据集内各样本 x ( i ) ∈ D = { x ( i ) , y ( i ) } i = 1 N , x ( i ) ∈ R p x^{(i)} \in \mathcal D = \{x^{(i)},y^{(i)}\}_{i=1}^N,x^{(i)} \in \mathbb R^p x(i)D={x(i),y(i)}i=1N,x(i)Rp之间的关联关系。而这种描述关联关系的操作,我们首先会想到内积
x ⋅ x ( i ) = x T [ x ( i ) ] x \cdot x^{(i)} = x^T [x^{(i)}] xx(i)=xT[x(i)]
如果涉及到一个非线性问题——或者说仅仅使用内积对关联关系的表达不够丰富,可以通过高维特征转换非线性问题转化为高维线性问题
{ x ⇒ ϕ ( x ) x ( i ) = ϕ ( x ( i ) ) ( i = 1 , 2 , ⋯ , N ) x T [ x ( i ) ] ⇒ [ ϕ ( x ) ] T ϕ ( x ( i ) ) \begin{cases} x \Rightarrow \phi(x) \\x^{(i)} = \phi(x^{(i)})(i=1,2,\cdots,N) \\ x^T[x^{(i)}] \Rightarrow [\phi(x)]^T \phi(x^{(i)}) \end{cases} xϕ(x)x(i)=ϕ(x(i))(i=1,2,,N)xT[x(i)][ϕ(x)]Tϕ(x(i))
低维特征转化为高维特征同样存在弊端。在核方法思想与核函数中介绍过:映射后的特征结果 ϕ ( x ) , \phi(x), ϕ(x),其特征维数远远超过原始特征维数 p p p,甚至是无限维。在这种情况下去计算 [ ϕ ( x ) ] T ϕ ( x ( i ) ) [\phi(x)]^T \phi(x^{(i)}) [ϕ(x)]Tϕ(x(i)),其计算代价是无法估量的。而核技巧提供了一种简化运算的方式。关于核函数 κ ( ⋅ ) \kappa(\cdot) κ()的定义表示如下:
κ [ x , x ( i ) ] = ⟨ ϕ ( x ) , ϕ ( x ( i ) ) ⟩ = [ ϕ ( x ) ] T ϕ ( x ( i ) ) \kappa \left[x,x^{(i)}\right] = \left\langle\phi(x),\phi(x^{(i)})\right\rangle= [\phi(x)]^T \phi(x^{(i)}) κ[x,x(i)]=ϕ(x),ϕ(x(i))=[ϕ(x)]Tϕ(x(i))
可以看出:核函数 κ ( ⋅ ) \kappa(\cdot) κ()的自变量是未经过高维转换的原始特征;而对应函数是高维转换后的内积结果。因而该函数的作用可以简化运算。最终我们可以通过核函数描述 x x x与数据集内所有样本 x ( i ) ( i = 1 , 2 , ⋯ , N ) x^{(i)}(i=1,2,\cdots,N) x(i)(i=1,2,,N)之间的关联关系
κ [ x , x ( i ) ] i = 1 , 2 , ⋯ , N \kappa \left[x,x^{(i)}\right] \quad i=1,2,\cdots,N κ[x,x(i)]i=1,2,,N

使用 Softmax \text{Softmax} Softmax函数对权重进行划分

此时已经得到 x x x所有样本 x ( i ) x^{(i)} x(i)核函数结果,这 N N N个结果有大有小,数值大的意味着样本之间的关联程度。从而可以将关联关系描述成 x x x与样本 x ( i ) x^{(i)} x(i)对应标签结果 y ( i ) y^{(i)} y(i)的权重 G ( x , x ( i ) ) \mathcal G(x,x^{(i)}) G(x,x(i))
G ( x , x ( i ) ) = κ ( x , x ( i ) ) ∑ j = 1 N κ ( x , x ( j ) ) \mathcal G(x,x^{(i)}) = \frac{\kappa(x,x^{(i)})}{\sum_{j=1}^{N}\kappa(x,x^{(j)})} G(x,x(i))=j=1Nκ(x,x(j))κ(x,x(i))
关于权重 G ( x , x ( i ) ) \mathcal G(x,x^{(i)}) G(x,x(i)),必然有如下结果:
∑ i = 1 N G ( x , x ( i ) ) = ∑ i = 1 N κ ( x , x ( i ) ) ∑ i = 1 N κ ( x , x ( i ) ) = 1 \sum_{i=1}^N \mathcal G(x,x^{(i)}) = \frac{\sum_{i=1}^{N} \kappa(x,x^{(i)})}{\sum_{i=1}^{N} \kappa(x,x^{(i)})} = 1 i=1NG(x,x(i))=i=1Nκ(x,x(i))i=1Nκ(x,x(i))=1
为什么是 Softmax \text{Softmax} Softmax函数呢——如果该核函数是一个指数函数。例如高斯核函数
将大括号内的项视作 Δ ( i ) \Delta^{(i)} Δ(i)
κ ( x , x ( i ) ) = exp ⁡ { − 1 2 σ 2 ∥ x − x ( i ) ∥ 2 ⏟ Δ ( i ) } \kappa (x,x^{(i)}) = \exp \left\{\underbrace{- \frac{1}{2 \sigma^2} \left\|x - x^{(i)} \right\|^2 }_{\Delta^{(i)}}\right\} κ(x,x(i))=exp Δ(i) 2σ21 xx(i) 2
那么 G ( x , x ( i ) ) \mathcal G(x,x^{(i)}) G(x,x(i))可表示为:
G ( x , x ( i ) ) = exp ⁡ { Δ ( i ) } ∑ j = 1 N exp ⁡ { Δ ( j ) } = Softmax ( Δ ( i ) ) \mathcal G(x,x^{(i)}) = \frac{\exp \{\Delta^{(i)}\}}{\sum_{j=1}^N \exp\{\Delta^{(j)}\}} = \text{Softmax}(\Delta^{(i)}) G(x,x(i))=j=1Nexp{Δ(j)}exp{Δ(i)}=Softmax(Δ(i))
最终可以得到如下权重向量
G ( x , D ) = [ κ ( x , x ( 1 ) ) ∑ j = 1 N κ ( x , x ( j ) ) , ⋯ , κ ( x , x ( N ) ) ∑ j = 1 N κ ( x , x ( j ) ) ] 1 × N \mathcal G(x,\mathcal D) = \left[\frac{\kappa(x,x^{(1)})}{\sum_{j=1}^N \kappa(x,x^{(j)})},\cdots,\frac{\kappa (x,x^{(N)})}{\sum_{j=1}^N \kappa(x,x^{(j)})} \right]_{1 \times N} G(x,D)=[j=1Nκ(x,x(j))κ(x,x(1)),,j=1Nκ(x,x(j))κ(x,x(N))]1×N

将权重与相应标签执行加权运算

得到权重向量 G ( x , D ) \mathcal G(x,\mathcal D) G(x,D)后,与对应标签向量 Y = ( y ( 1 ) , ⋯ , y ( N ) ) T \mathcal Y = (y^{(1)},\cdots,y^{(N)})^T Y=(y(1),,y(N))T内积运算,得到关于陌生样本 x x x的预测结果 f ( x ) f(x) f(x)
本质上就是关于标签 y ( i ) ( i = 1 , 2 , ⋯ , N ) y^{(i)}(i=1,2,\cdots,N) y(i)(i=1,2,,N)的加权平均数~
f ( x ) = G ( x , D ) ⋅ Y = κ ( x , x ( 1 ) ) ∑ j = 1 N κ ( x , x ( j ) ) ⋅ y ( 1 ) + ⋯ κ ( x , x ( N ) ) ∑ j = 1 N κ ( x , x ( j ) ) ⋅ y ( N ) \begin{aligned} f(x) & = \mathcal G(x,\mathcal D) \cdot \mathcal Y \\ & = \frac{\kappa(x,x^{(1)})}{\sum_{j=1}^N \kappa(x,x^{(j)})} \cdot y^{(1)} + \cdots \frac{\kappa(x,x^{(N)})}{\sum_{j=1}^N \kappa(x,x^{(j)})} \cdot y^{(N)} \end{aligned} f(x)=G(x,D)Y=j=1Nκ(x,x(j))κ(x,x(1))y(1)+j=1Nκ(x,x(j))κ(x,x(N))y(N)

Nadaraya-Watson \text{Nadaraya-Watson} Nadaraya-Watson核回归代码示例

关于径向基核函数与高斯核函数

在上述注意力机制基本介绍一节中,我们模糊了径向基核函数高斯核函数的区别。这里提出一些新的认识。两种核函数的公式表示如下:
{ RBF :  κ ( x , x ( i ) ) = exp ⁡ ( − γ ⋅ ∥ x − x ( i ) ∥ 2 ) Gaussian :  κ ( x , x ( i ) ) = exp ⁡ [ − 1 2 σ 2 ∥ x − x ( i ) ∥ 2 ] \begin{cases} \begin{aligned} & \text{RBF : } \kappa (x,x^{(i)}) = \exp ( - \gamma \cdot \|x - x^{(i)}\|^2) \\ & \text{Gaussian : } \kappa(x,x^{(i)}) = \exp \left[- \frac{1}{2\sigma^2} \|x - x^{(i)}\|^2 \right] \end{aligned} \end{cases} RBF : κ(x,x(i))=exp(γxx(i)2)Gaussian : κ(x,x(i))=exp[2σ21xx(i)2]
相比之下,径向基核函数它的参数 γ ∈ [ 0 , 1 ] \gamma \in [0,1] γ[0,1],相比高斯核函数 σ \sigma σ的范围描述的更加方便

关于高维向量的核函数表示

根据上面公式,高维向量的核函数表示,其核心步骤是范数的表示。可以使用numpy模块中的numpy.linalg.norm()方法进行表示。下面分别通过调用径向基核函数模块sklearn.metrics.pairwise.rbf_kernel以及手写方式进行实现:

import numpy as np
from sklean.metrics.pairwise import rbf_kerneldef RBFKernelFunction(xInput, xSample, gamma):def NormCalculation(xInput, xSample):NormResult = np.linalg.norm(xInput - xSample)return NormResult ** 2return np.exp((-1 * gamma) * NormCalculation(xInput, xSample))a = np.array([1,2,3,4])
b = np.array([5,6,7,4])SklearnOut = rbf_kernel(a.reshape(1,-1),b.reshape(1,-1),gamma=0.5)
ManuOut = RBFKernelFunction(a.reshape(1,-1),b.reshape(1,-1),gamma=0.5)
# [[3.77513454e-11]]
print(SklearnOut)
# 3.775134544279111e-11
print(ManuOut)

关于回归任务的相关示例

完整代码如下:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import math
from tqdm import tqdmdef ReadXlsx(Path):Df = pd.read_excel(Path,sheet_name="Sheet1")return Dfdef DealTokenAndLabel(Df):def DivideTokenAndLabel(ListInput):Label = ListInput.pop(3)return ListInput,Labeldef LinearCorrectOperation(Input,mode="Token"):assert mode in ["Token","Label"]if mode == "Token":OriginalToken = Input[3]UpdateToken = OriginalToken / 10.0Input[3] = round(UpdateToken,3)else:UpdateLabel = Input * 10.0Input = round(UpdateLabel,4)return InputDataList = list()LabelList = list()for (Ids,i) in Df.iterrows():Token,Label = DivideTokenAndLabel(list(i))UpdateToken = LinearCorrectOperation(Token)UpdateLabel = LinearCorrectOperation(Label,mode="Label")DataList.append(np.array(UpdateToken))LabelList.append(np.array(UpdateLabel))return DataList,LabelListdef AlgorithmProcess(DataList,LabelList,gamma,mode="RBF"):assert mode in ["Linear","RBF"]def RBFKernelFunction(xInput,xSample,gamma):def NormCalculation(xInput, xSample):NormResult = np.linalg.norm(xInput - xSample)return NormResult ** 2return np.exp((-1 * gamma) * NormCalculation(xInput, xSample))def LinearKernelFunction(xInput,xSample):return np.dot(xInput,xSample)def SoftmaxFunction(xInput,xSample,gamma,mode):if mode == "Linear":return LinearKernelFunction(xInput,xSample) / sum(LinearKernelFunction(xInput,i) for i in DataList)else:return RBFKernelFunction(xInput,xSample,gamma) / sum(RBFKernelFunction(xInput,i,gamma) for i in DataList)def NWKernalRegressionResult(xInput,gamma,mode):KernelRegressionList = list()for _,(TokenSample,LabelSample) in enumerate(zip(DataList,LabelList)):if (TokenSample == xInput).all():continueelse:if mode == "RBF":xInput = xInput.reshape(1, -1)TokenSample = TokenSample.reshape(1, -1)SoftmaxCoeff = SoftmaxFunction(xInput, TokenSample, gamma, mode)KernelRegressionList.append(SoftmaxCoeff * LabelSample)return sum(KernelRegressionList)return [NWKernalRegressionResult(i,gamma,mode) for i in DataList]# return NWKernalRegressionResult(xInput,gamma)def EmpiricRiskStatic(mode):def EmpiricRisk(NWKernelPredictList,LabelList,mode="FirstOrder"):assert mode in ["FirstOrder","SecondOrder"]ErrorList = list()for _,(NWKernelPredict,Label) in enumerate(zip(NWKernelPredictList,LabelList)):if mode == "FirstOrder":ErrorList.append(abs(NWKernelPredict - Label))else:ErrorList.append((NWKernelPredict - Label) ** 2)return sum(ErrorList) / len(ErrorList)GammaLimits = list(np.linspace(0, 0.5, 2000))EmpiricRiskList = list()EmpiricRiskListSecond = list()for GammaChoice in tqdm(GammaLimits):NWKernelPredictList = AlgorithmProcess(DataList,LabelList,GammaChoice,mode=mode)EmpiricRiskResult = EmpiricRisk(NWKernelPredictList, LabelList)EmpiricRiskList.append(EmpiricRiskResult)EmpiricRiskResultSecond = EmpiricRisk(NWKernelPredictList,LabelList,mode="SecondOrder")EmpiricRiskListSecond.append(EmpiricRiskResultSecond)plt.scatter(GammaLimits,EmpiricRiskList,s=2,c="tab:blue")plt.scatter(GammaLimits,EmpiricRiskListSecond,s=2,c="tab:orange")plt.savefig("EmpiricRisk.png")plt.show()if __name__ == '__main__':Path = r""DataList, LabelList = DealTokenAndLabel(ReadXlsx(Path))EmpiricRiskStatic(mode="RBF")

关于使用 Nadaraya-Watson \text{Nadaraya-Watson} Nadaraya-Watson核回归时,需要注意的点:

  • 由于 Nadaraya-Watson \text{Nadaraya-Watson} Nadaraya-Watson核回归自身是懒惰学习方法,因此,这里唯一的参数就是径向基核函数中描述的 γ \gamma γ。而针对选择最优 γ \gamma γ,这里使用的目标函数经验风险 ( Empiric Risk ) (\text{Empiric Risk}) (Empiric Risk)
    J ( γ ) = E P ^ d a t a { L [ f ( x ( i ) ; γ ) , y ( i ) ] } = 1 M ∑ i = 1 M L [ f ( x ( i ) ; γ ) , y ( i ) ] \mathcal J(\gamma) =\mathbb E_{\hat {\mathcal P}_{data}} \left\{\mathcal L[f(x^{(i)};\gamma),y^{(i)}]\right\} = \frac{1}{\mathcal M} \sum_{i=1}^{\mathcal M} \mathcal L[f(x^{(i)};\gamma),y^{(i)}] J(γ)=EP^data{L[f(x(i);γ),y(i)]}=M1i=1ML[f(x(i);γ),y(i)]
    其中 L [ f ( x ( i ) ; γ ) ] \mathcal L[f(x^{(i)};\gamma)] L[f(x(i);γ)]表示关于 x ( i ) x^{(i)} x(i)预测结果 f ( x ( i ) ) f(x^{(i)}) f(x(i))真实标签 y ( i ) y^{(i)} y(i)之间的差异性结果,也就是损失函数 L ( ⋅ ) \mathcal L(\cdot) L() x ( i ) x^{(i)} x(i)点处的结果。目标函数确定后,这里的处理方式是:

    • γ \gamma γ确定的情况下,将数据集 P ^ d a t a \hat {\mathcal P}_{data} P^data中的每一个样本抽取出来,并使用剩余样本进行预测;
      值得注意的是:在抽取操作结束后,使用剩余样本做预测。因为如果被抽取样本依然保留在数据集内,那么在计算权重系数 κ ( x , x ( i ) ) ∑ j = 1 N κ ( x , x ( j ) ) \begin{aligned}\frac{\kappa(x,x^{(i)})}{\sum_{j=1}^N \kappa (x,x^{(j)})}\end{aligned} j=1Nκ(x,x(j))κ(x,x(i))过程中,数据集内与被抽取样本相同的样本其权重必然占据极高比重,因为该项的分子必然是 1 ( e 0 ) 1(e^0) 1(e0),从而该样本的预测结果会被数据集内相同的样本进行主导或者控制。个人实践踩过的坑~
    • 在所有样本均被遍历一次后,计算 J ( γ ) \mathcal J(\gamma) J(γ),记录并修改 γ \gamma γ,执行下一次迭代。从而通过统计的方式得到 γ ∈ [ 0 , 1 ] \gamma \in [0,1] γ[0,1]中的最优解
  • 关于损失函数 L [ f ( x ( i ) ; γ ) , y ( i ) ] \mathcal L[f(x^{(i)};\gamma),y^{(i)}] L[f(x(i);γ),y(i)],可以使用曼哈顿距离( 1 1 1阶)或者欧几里得距离( 2 2 2阶)对标签之间的差异性进行描述:
    无论 f ( x ( i ) ; γ ) f(x^{(i)};\gamma) f(x(i);γ)还是 y ( i ) y^{(i)} y(i)都是标量形式。因而没有使用范数进行表达。
    L [ f ( x ( i ) ; γ ) , y ( i ) ] = { ∣ f ( x ( i ) ; γ ) − y ( i ) ∣ ⇒ Manhattan Distance [ f ( x ( i ) ; γ ) − y ( i ) ] 2 ⇒ Euclidean Distance \mathcal L[f(x^{(i)};\gamma),y^{(i)}] = \begin{cases} \left|f(x^{(i)};\gamma) - y^{(i)} \right| \quad \Rightarrow \text{Manhattan Distance}\\ \quad \\ \left[f(x^{(i)};\gamma) - y^{(i)} \right]^2 \quad \Rightarrow \text{Euclidean Distance} \end{cases} L[f(x(i);γ),y(i)]= f(x(i);γ)y(i) Manhattan Distance[f(x(i);γ)y(i)]2Euclidean Distance

这里基于某数据集的回归任务,关于曼哈顿距离、欧式距离作为损失函数, J ( γ ) \mathcal J(\gamma) J(γ) γ \gamma γ之间的关联关系表示如下:
其中横坐标表示 γ \gamma γ的取值;纵坐标表示 J ( γ ) \mathcal J(\gamma) J(γ)的映射结果。
某回归任务的经验风险结果
其中蓝色点形状表示曼哈顿距离作为损失函数的图像结果;而橙色点形状表示欧几里得距离作为损失函数的图像结果。从图中可以看出:在相似位置可以得到目标函数的最小值
需要注意的是,两种函数无法相互比较,因为两者对应目标函数的值域不同。

个人想法

虽然通过统计的方式得到了 γ \gamma γ的最优解,但它可能并不准。或者说:基于当前数据集 P ^ d a t a \hat {\mathcal P}_{data} P^data,使用径向基核函数条件下的最准结果。其他优化的方式有:

  • 核函数的选择;
    一般情况下,线性核函数本身是够用的。
  • 扩充样本数据;
    • 在最早的概率与概率模型中介绍过,模型预测的不准的本质原因是预测模型与真实模型之间的差异性较大。而在 Nadaraya-Watson \text{Nadaraya-Watson} Nadaraya-Watson核回归中,并没有涉及到具体模型。因而反馈的结果是:当前训练集所描述的概率分布真实分布之间存在较大差距
    • 由于真实分布是客观存在的,也就是说训练集的样本越多,分布就越稳定。体现在参数 γ \gamma γ中的效果是:在样本数量较少时,不同的数据集对应的 γ \gamma γ差异性可能很大(波动较大);随着样本数量的增多, γ \gamma γ会逐渐趋于稳定

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

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

相关文章

Linux centos7 bash编程——-求质数和

训练项目:使用函数求质数和。 定义一个函数IsPrime(),据此判断一个数是否为质数 由用户输入一个整数,求出比此数大的两个最小质数之和。 一、解决思路: 1.先在键盘上输入一个整数 2.求出比此数大的最小质数 3.再求出比此质数大的另一个…

使用正则提取字符串中的json数据

需求: 我们有一个这样的字符串 以下数据:{"title": "标题一", "text": "内容一", "tag": "tag1"}{"title": "标题二", "text": "内容二", &quo…

ChatGPT 实现动态地图可视化展示

地图可视化分析有许多优点和好处: 1.直观理解:地图可视化使得复杂的数据更易于理解。通过地图可视化,人们可以直观地看到地理位置、地区之间的关系以及空间分布的模式。 2.提高决策效率:地图可视化可以帮助决策者快速理解和解释数据,从而提高决策效率。 3.高效的数据整…

【java web】论坛实现帖子回复(仿牛客网),帮助大家理清逻辑

一、common表的情况 CREATE TABLE comment (id int NOT NULL AUTO_INCREMENT,user_id int DEFAULT NULL,entity_type int DEFAULT NULL,entity_id int DEFAULT NULL,target_id int DEFAULT NULL,content text,status int DEFAULT NULL,create_time timestamp NULL DEFAULT NUL…

【Pandas 入门-5】Pandas 画图

Pandas 画图 除了结合 matplotlib 与 seaborn 画图外,Pandas 也有自己的画图函数plot,它的语法一般为: DataFrame.plot(xNone,yNone, kindline,subplotsFalse, titleNone)x横坐标数据y纵坐标数据kind默认是线图,还可以是‘bar’…

基于单片机的串行通信发射机设计

一、项目介绍 串行通信是一种常见的数据传输方式,允许将数据以比特流的形式在发送端和接收端之间传输。当前实现基于STC89C52单片机的串行通信发射机,通过红外发射管和接收头实现自定义协议的数据无线传输。 二、系统设计 2.1 单片机选择 在本设计中&…

代码随想录二刷day04

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、力扣24. 两两交换链表中的节点二、力扣19. 删除链表的倒数第 N 个结点三、力扣面试题 02.07. 链表相交四、力扣142. 环形链表 II 前言 一、力扣24. 两两交换…

【AI】《动手学-深度学习-PyTorch版》笔记(二十):图像增强、微调

AI学习目录汇总 1、图像增强 图像增强可以扩展训练样本数量、减小对某个属性的依赖。比如,裁剪图像,可以减少模型对对象出现位置的依赖;调整亮度、颜色等因素来降低模型对颜色的敏感度等 1.1、准备工作 头文件 %matplotlib inline:图表直接嵌入到Notebook中,本人使用的…

缓存技术(缓存穿透,缓存雪崩,缓存击穿)

大家好 , 我是苏麟 , 今天聊一聊缓存 . 这里需要一些Redis基础 (可以看相关文章等) 本文章资料来自于 : 黑马程序员 如果想要了解更详细的资料去黑马官网查看 前言:什么是缓存? 缓存,就是数据交换的 缓冲区 (称作Cache [ kʃ ] ),俗称的缓存就是缓冲区内的数据,是存贮数据的…

C语言——多文件编程

多文件编程 把函数声明放在头文件xxx.h中,在主函数中包含相应头文件在头文件对应的xxx.c中实现xxx.h声明的函数 防止头文件重复包含 当一个项目比较大时,往往都是分文件,这时候有可能不小心把同一个头文件 include 多次,或者头…

十六、pikachu之SSRF

文章目录 1、SSRF概述2、SSRF(URL)3、SSRF(file_get_content) 1、SSRF概述 SSRF(Server-Side Request Forgery:服务器端请求伪造):其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能&…

Spring容器及实例化

一、前言 Spring 容器是 Spring 框架的核心部分,它负责管理和组织应用程序中的对象(Bean)。Spring 容器负责创建、配置和组装这些对象,并且可以在需要时将它们提供给应用程序的其他部分。 Spring 容器提供了两种主要类型的容器&…

面试系列 - JVM内存模型和调优详解

目录 一、JVM内存模型 1. 程序计数器(Program Counter Register): 2.Java虚拟机栈(Java Virtual Machine Stacks): 3. 本地方法栈(Native Method Stack): 5. 方法区…

matlab绘制局部放大图

ZoomPlot是一个交互式的matlab局部绘图库,其github仓库地址为 https://github.com/iqiukp/ZoomPlot-MATLAB。在使用库之前需要先将库下载到本地,可以直接添加到matlab的库中,也可以放在项目文件中直接使用。 简单使用 其实使用这个库只需要…

【SpringCloud】SpringCloud整合openFeign

文章目录 前言1. 问题分析2. 了解Feign3. 项目整合Feign3.1 引入依赖3.2 添加注解3.3 编写Feign客户端3.4 测试3.5 总结 4. 自定义配置4.1 配置文件方式4.2 Java代码方式 5. Feign使用优化5.1 引入依赖5.2 配置连接池 6. Feign最佳实践6.1 继承方式6.2 抽取方式 前言 微服务远…

【ES6 新特性】

ES6 新特性 1、let 声明变量2、const 声明常量(只读变量)3、解构表达式1)、数组解构2)、对象解构 4、字符串扩展1)、几个新的 API2)、字符串模板 5、函数优化1)、函数参数默认值2)、…

MySQL连接池配置及FullGC分析

本文主要讲述MySQL连接池配置不合适时,由于MySQL以虚引用的方式作为线程清理的后备手段,导致JVM年老代随时间缓慢增长,直至FullGC的问题。为了优化数据库连接池配置,使得JVM进行尽量少的FullGC导致服务故障,本文提供了…

解决springboot项目中的groupId、package或路径的混淆问题

对于像我一样喜欢跳跃着学习的聪明人来说,肯定要学springboot,什么sevlet、maven、java基础,都太老土了,用不到就不学。所以古代的聪明人有句话叫“书到用时方恨少”,测试开源项目时,编译总是报错&#xff…

配置化开发的核心设计 - Schema

前端配置化SchemaServerless FaaS BaaS useImperativeHandle() react-helmet 参考链接 schema进入

Multicast IP Interface

该模块通过多播IPv4和IPv6在UDP上实现CAN和CAN FD消息的传输。此虚拟接口允许在多个进程甚至主机之间进行通信。这与虚拟接口不同,虚拟接口只能在单个进程中传递消息,但不需要网络堆栈。 它在UDP上运行以具有尽可能低的延迟(与使用TCP相反),并且因为正常的IP多播本质上是…