T01_神经网络

感知机

感知机是神经网络算法最底层的算法支持。

数学模型:

z=w1x1+w2x2+...+wnxn+bz = w_1x_1 + w_2x_2 +...+ w_nx_n + bz=w1x1+w2x2+...+wnxn+b

其中bbb称为感知机的偏置(Bias),一维向量w=[w1,w2,...,wn]w = [w_1,w_2,...,w_n]w=[w1,w2,...,wn]称为感知机的权值(weight),z称为感知机的净活性值。

上式写成向量形式:

z=wTx+bz = w^Tx + bz=wTx+b

通过在线性模型后添加激活函数后得到活性值(Activation) a:

a = \\sigma(z) = \\sigma(w\^Tx + b)

其中激活函数可以是阶跃函数(Step function) a={1wTx+b≥00wTx+b<0a = \begin{cases} 1 & w^Tx + b \ge 0 \\ 0 & w^Tx + b < 0 \end{cases}a={10wTx+b≥0wTx+b<0 ,也可以是符号函数(Sign function) a={1wTx+b≥0−1wTx+b<0a = \begin{cases} 1 & w^Tx + b \ge 0 \\ -1 & w^Tx + b < 0 \end{cases}a={1−1wTx+b≥0wTx+b<0

添加激活函数后,感知机可以用来完成二分类任务。阶跃函数和符号函数在 z=0 处是不连续的,其他位置导数为 0,无法利用梯度下降算法进行参数优化。

全连接层

感知机模型的不可导特性严重约束了它的潜力,使得它只能解决极其简单的任务。可以将不连续的阶跃激活函数换成了其它平滑连续可导的激活函数,并通过堆叠多个网络层来增强网络的表达能力。

下面构成 3 输入节点、2 个输出节点的网络层:

第一个输出节点的输出为:o1=σ(w11x1+w21x2+w31x3+b1)o_1 = \sigma(w_{11}x_1+w_{21}x_2+w_{31}x_3 + b1)o1=σ(w11x1+w21x2+w31x3+b1)

第二个输出节点的输出为:o2=σ(w12x1+w22x2+w32x3+b2)o_2 = \sigma(w_{12}x_1+w_{22}x_2+w_{32}x_3 + b2)o2=σ(w12x1+w22x2+w32x3+b2)

输出向量为o=[o1,o2]o = [o_1,o_2]o=[o1,o2],整个网络层可以通过矩阵关系式表达:[o1o2]=[x1x2x3]@[w11w12w21w22w31w32]+[b1b2]\begin{bmatrix}o_1&o_2\end{bmatrix} = \begin{bmatrix}x_1 &x_2 &x_3\end{bmatrix}@\begin{bmatrix}w_{11}&w_{12}\\w_{21}&w_{22}\\w_{31}&w_{32} \end{bmatrix} +\begin{bmatrix}b_1&b_2\end{bmatrix}[o1o2]=[x1x2x3]@ w11w21w31w12w22w32 +[b1b2]

简化一下:O = X@W+b

由于每个输出节点与全部的输入节点相连接,这种网络层称为全连接层(Fully-connected Layer)。

X 是输入矩阵, shape 定义为[n,din][n,d_{in}][n,din],𝑏为样本数量,dind_{in}din为输入节点数;𝑾矩阵叫做全连接层的权值矩阵,shape定义为[din,dout][d_{in},d_{out}][din,dout];𝒃向量叫做全连接层的偏置向量,shape 定义为[dout][d_{out}][dout]。

张量方式实现

通过张量实现全连接层,只需要定义好权值张量W 和偏置张量b,并利用批量矩阵相乘函数 tf.matmul()即可完成网络层的计算。

python 复制代码
import tensorflow as tf
# 要求输入特征数为784,输出节点数为256
x = tf.random.normal([2,784]) # 输入X矩阵,2个样本,输入特征长度784
w1 = tf.Variable(tf.random.truncated_normal([784,256],stddev=0.1)) # 权值矩阵𝑾,shape 为[784,256],并采用正态分布初始化𝑾
b1 = tf.Variable(tf.zeros([256])) # 偏置向量𝒃的 shape 定义为[256]
o1 = tf.matmul(x,w1) +b1 # 最终全连接层的输出𝑶的 shape 为[2,256]
o1 = tf.nn.relu(o1)

层方式实现

tensorlow 中有更高层、使用更方便的层实现方式:layers.Dense(units, activation),不用上面那么麻烦。

通过 layer.Dense 类,只需要指定输出节点数 Units 和激活函数类型 activation 即可。

python 复制代码
from tensorflow.keras import layers
fc = layers.Dense(256,activation=tf.nn.relu) # 创建全连接层,指定输出节点数和激活函数
h1 = fc(x) # 通过 fc 类实例完成一次全连接层的计算,返回输出张量
print(fc.kernel) # 获取 Dense 类的权值矩阵
print(fc.bias) # 获取 Dense 类的偏置向量

神经网络

通过层层堆叠全连接层,保证前一层的输出节点数与当前层的输入节点数匹配,即可堆叠出任意层数的网络。而这种由神经元相互连接而成的网络叫做神经网络。

上图中通过堆叠 4 个全连接层,可以获得层数为 4 的神经网络,由于每层均为全连接层,称为全连接网络。其中第 1~3 个全连接层在网络中间,称之为隐藏层 1、2、3,最后一个全连接层的输出作为网络的输出,称为输出层。隐藏层 1、2、3 的输出节点数分别为[256,128,64],输出层的输出节点数为 10。

网络的结构配置等超参数可以按着经验法则自由设置,只需要遵循少量的约束即可:

  • 隐藏层 1 的输入节点数需和数据的实际特征长度匹配
  • 每层的输入层节点数与上一层输出节点数匹配
  • 输出层的激活函数和节点数需要根据任务的具体设定进行设计

隐层的shape设置可以通过AutoML 技术搜索得到(类似sklearn中的网格搜索)。

张量方式实现

对于多层神经网络需要分别定义各层的权值矩阵𝑾和偏置向量𝒃。有多少个全连接层,则需要相应地定义数量相当的𝑾和𝒃,并且每层的参数只能用于对应的层,不能混淆使用。

python 复制代码
x = tf.random.normal([4,28*28])

# 隐藏层 1 张量
w1 = tf.Variable(tf.random.truncated_normal([784,256],stddev=0.1)) 
b1 = tf.Variable(tf.zeros([256]))
# 隐藏层 2 张量
w2 = tf.Variable(tf.random.truncated_normal([256,128],stddev=0.1))
b2 = tf.Variable(tf.zeros([128]))
# 隐藏层 3 张量
w3 = tf.Variable(tf.random.truncated_normal([128,64],stddev=0.1))
b3 = tf.Variable(tf.zeros([64]))
# 隐藏层 4 张量
w4 = tf.Variable(tf.random.truncated_normal([64,10],stddev=0.1))
b4 = tf.Variable(tf.zeros([10]))

with tf.GradientTape() as tape: #  梯度记录器
    # 隐藏层 1 前向计算
    h1 = x@w1 + tf.broadcast_to(b1,[x.shape[0],256]) 
    h1 = tf.nn.relu(h1)
    # 隐藏层 2 前向计算
    h2 = h1@w2+b2
    h2 = tf.nn.relu(h2)
    # 隐藏层 3 前向计算
    h3 = h2@w3 + b3
    h3 = tf.nn.relu(h3)
    # 输出层前向计算 ,最后一层是否需要添加激活函数通常视具体的任务而定
    h4 = h3@w4+b4
del tape

在使用 TensorFlow 自动求导功能计算梯度时,需要将前向计算过程放置在tf.GradientTape()环境中,利用 GradientTape 对象的 gradient()方法自动求解参数的梯度,并利用 optimizers 对象更新参数。

层方式实现

对于常规的网络层,通过层方式实现起来更加简洁高效。

python 复制代码
from tensorflow.keras import layers

fc1 = layers.Dense(256, activation=tf.nn.relu) # 隐藏层 1
fc2 = layers.Dense(128, activation=tf.nn.relu) # 隐藏层 2
fc3 = layers.Dense(64, activation=tf.nn.relu) # 隐藏层 3
fc4 = layers.Dense(10, activation=None) # 输出层

x = tf.random.normal([4,28*28])
h1 = fc1(x) # 通过隐藏层 1 得到输出
h2 = fc2(h1) # 通过隐藏层 2 得到输出
h3 = fc3(h2) # 通过隐藏层 3 得到输出
h4 = fc4(h3) # 通过输出层得到网络输出

对于这种数据依次向前传播的网络,也可以通过 Sequential 容器封装成一个网络大类对象,调用大类的前向计算函数一次即可完成所有层的前向计算,使用起来更加方便

python 复制代码
from tensorflow.keras import Sequential

# 通过 Sequential 容器封装为一个网络类
model = Sequential([
	layers.Dense(256, activation=tf.nn.relu) , # 创建隐藏层 1
    layers.Dense(128, activation=tf.nn.relu) , # 创建隐藏层 2
    layers.Dense(64, activation=tf.nn.relu) , # 创建隐藏层 3
    layers.Dense(10, activation=None) , # 创建输出层
])
out = model(x) # 前向计算得到输出

优化目标

把神经网络从输入到输出的计算过程叫做前向传播或前向计算。前向传播过程是数据张量从第一层流动至输出层的过程,即从输入数据开始,途径每个隐藏层,直至得到输出并计算误差。

前向传播的最后一步就是完成误差的计算:L=g(fθ(x),y)\mathcal{L} = g(f_{\theta}(x),y)L=g(fθ(x),y) ,其中fθ(.)f_{\theta}(.)fθ(.)代表了利用θ\thetaθ参数化的神经网络模型,g(.)g(.)g(.)称为误差函数,用来描述当前网络的预测值fθ(x)f_{\theta}(x)fθ(x)与真实标签yyy之间的差距度量,比如常用的均方差误差函数。L\mathcal{L}L 称为网络的误差(loss),一般为标量。

最终目的是希望通过在训练集Dtrain\mathbb{D}^{train}Dtrain上面学习到一组参数θ\thetaθ使得训练的误差ℒ最小:θ∗=argmin⏟θg(fθ(x),y),x∈Dtrain\theta^* = \begin{matrix} \underbrace {arg min} \\ \theta\end{matrix}g(f_{\theta}(x),y),x \in \mathbb{D}^{train}θ∗= argminθg(fθ(x),y),x∈Dtrain

上述的最小化优化问题一般采用误差反向传播算法(BP)来求解网络参数θ\thetaθ的梯度信息,并利用梯度下降(GD)算法迭代更新参数:θ′=θ−η.ΔθL\theta^\prime = \theta - \eta . \Delta_{\theta}\mathcal{L}θ′=θ−η.ΔθL

其中η\etaη为学习率(是个常量,学是机器学习中控制模型参数更新步长的关键超参数‌,直接影响模型训练的收敛速度和最终性能)

从另一个角度来理解神经网络,它完成的是特征的维度变换的功能,原始的特征通常具有较高的维度,包含了很多底层特征及无用信息,通过神经网络的层层特征变换,将较高的维度降维到较低的维度,此时的特征一般包含了与任务强相关的高层抽象特征信息,通过对这些特征进行简单的逻辑判定即可完成特定的任务,如图片的分类

网络的参数量是衡量网络规模的重要指标,计算全连接层的参数量的方式:𝑑in.𝑑out+𝑑out𝑑_{in} . 𝑑_{out} + 𝑑_{out}din.dout+dout。比如784 → 256 → 128 → 64 → 10,总参数量的计算表达式为:256 ∙ 784 + 256 + 128 ∙ 256 + 128 + 64 ∙ 128 + 64 + 10 ∙ 64 + 10 = 242762

激活函数

Sigmoid

Sigmoid 函数也叫 Logistic 函数,定义为:Sigmoid(x)≜1/(1+e−x)Sigmoid(x) \triangleq 1/(1+e^{-x})Sigmoid(x)≜1/(1+e−x)

它的一个优良特性就是能够把 x∈Rx \in Rx∈R 的输入"压缩"到 x∈(0,1)x \in (0,1)x∈(0,1)区间,区间的数值常用来表示以下意义:

  • 概率分布 (0,1)区间的输出和概率的分布范围[0,1]契合,可以通过 Sigmoid 函数将输出转译为概率输出
  • 信号强度 一般可以将 0~1 理解为某种信号的强度,如像素的颜色强度,1 代表当前通道颜色最强,0 代表当前通道无颜色;抑或代表门控值(Gate)的强度,1 代表当前门控全部开放,0 代表门控关闭

Sigmoid 函数连续可导,可以直接利用梯度下降算法优化网络参数,应用的非常广泛。

python 复制代码
x = tf.linspace(-6.,6.,120)
x_sig = tf.nn.sigmoid(x)

import matplotlib.pyplot as plt
import numpy as np

fig ,(ax1,ax2) = plt.subplots(1,2,figsize=(8,4))

ax2.plot(np.arange(-6,6,0.1),x)   
ax1.plot(np.arange(-6,6,0.1),x_sig.numpy())
# 可以看到,向量中元素值的范围由[−6,6]映射到(0,1)的区间。

Sigmoid 函数在输入值较大或较小时容易出现梯度值接近于 0 的现象,称为梯度弥散现象。出现梯度弥散现象时,网络参数长时间得不到更新,导致训练不收敛或停滞不动的现象发生。

ReLU

在 ReLU(REctified Linear Unit,修正线性单元)激活函数定义为:ReLU(x)≜max(0,x)ReLU(x) \triangleq max(0,x)ReLU(x)≜max(0,x)

ReLU 对小于 0 的值全部抑制为 0;对于正数则直接输出

python 复制代码
x_relu = tf.nn.relu(x)

fig ,(ax1,ax2) = plt.subplots(1,2,figsize=(8,4))

ax2.plot(np.arange(-6,6,0.1),x)
ax1.plot(np.arange(-6,6,0.1),x_relu.numpy())
# 经过 ReLU 激活函数后,负数全部抑制为 0,正数得以保留。

ReLU 函数在x < 0时导数值恒为 0,也可能会造成梯度弥散现象

LeakyReLU

为了克服梯度弥散现象,LeakyReLU 函数被提出,表达式为:LeakyReLU≜{xx≥0pxx<0LeakyReLU \triangleq \begin{cases}x & x\ge 0 \\ px & x<0 \end{cases}LeakyReLU≜{xpxx≥0x<0

其中p为用户自行设置的某较小数值的超参数,如 0.02 等。当p= 0时,LeayReLU 函数退化为 ReLU 函数;当p ≠ 0时,x < 0处能够获得较小的导数值p,从而避免出现梯度弥散现象。

python 复制代码
x_leaky = tf.nn.leaky_relu(x,alpha=0.1)

fig ,(ax1,ax2) = plt.subplots(1,2,figsize=(8,4))

ax2.plot(np.arange(-6,6,0.1),x)
ax1.plot(np.arange(-6,6,0.1),x_leaky.numpy())

其中 alpha (sklearn的神经网络中也有这个参数)参数代表p。tf.nn.leaky_relu 对应的类为 layers.LeakyReLU,可以通过LeakyReLU(alpha)创建 LeakyReLU 网络层,并设置p参数,像 Dense 层一样将 LeakyReLU层放置在网络的合适位置。

Tanh

Tanh函数能够把 x∈Rx \in Rx∈R 的输入"压缩"到 x∈(−1,1)x \in (-1,1)x∈(−1,1)区间,定义为:tanh(x)=(ex−e−x)/(ex+e−x)=2⋅sigmoid(2x)−1tanh(x) = (e^x-e^{-x})/(e^x+e^{-x}) = 2 \cdot sigmoid(2x)-1tanh(x)=(ex−e−x)/(ex+e−x)=2⋅sigmoid(2x)−1

python 复制代码
x_tanh = tf.nn.tanh(x)
plt.plot(np.arange(-6,6,0.1),x_tanh.numpy())
plt.axhline(0,color='gray',linewidth=0.5)
plt.axvline(0,color='gray',linewidth=0.5)
# 可以看到向量元素值的范围被映射到(−1,1)之间

输出层设计

输出层和所有的隐藏层一样,完成维度变换、特征提取的功能,需要根据具体的任务场景来决定是否使用激活函数,以及使用什么类型的激活函数等。

常见的几种输出类型包括:

  • oi∈Rdo_i \in R^doi∈Rd :输出属于整个实数空间,或者某段普通的实数空间,比如函数值趋势的预测,年龄的预测问题等。
  • oi∈[0,1]o_i \in [0,1]oi∈[0,1]:输出值特别地落在[0, 1]的区间,如图片生成,图片像素值一般用[0, 1]区间的值表示;或者二分类问题的概率,如硬币正反面的概率预测问题。
  • oi∈[0,1],∑ioi=1o_i \in [0,1],\sum_i o_i = 1oi∈[0,1],∑ioi=1:输出值落在[0,1]的区间,并且所有输出值之和为 1,常见的如多分类问题。
  • oi∈[−1,1]o_i \in [-1,1]oi∈[−1,1]:输出值在[-1, 1]之间

普通实数空间

这一类问题比较普遍,像年龄的预测、房价的预测等都属于整个或者部分连续的实数空间,输出层可以不加激活函数(类似于sklearn中的回归)。误差的计算直接基于最后一层的输出o 和真实值y 进行计算,如采用均方差误差函数度量输出值o 与真实值y之间的距离:

L=g(o,y)\mathcal{L} = g(o,y)L=g(o,y)

其中g代表了某个具体的误差计算函数,例如 MSE 等。

[0,1]区间

输出值属于[0,1]区间也比较常见,比如图片的生成、二分类问题等。

一般会将图片的像素值归一化到[0,1]区间,Sigmoid 函数刚好具有此功能。

对于二分类问题,输出层可以只设置一个节点,表示某个事件 A 发生的概率𝑃(A|x),x为网络输入。利用网络的输出标量o表示正面事件出现的概率,那么反面事件出现的概率即为1 − o。此时只需要在输出层的净活性值z后添加 Sigmoid 函数即可将输出转译为概率值。

除了可以使用单个输出节点表示事件 A 发生的概率𝑃(A|x)外,还可以分别预测𝑃(A|x)和𝑃(A̅|x)(A̅表示事件 A 的对立事件),并满足约束P(A∣x)+P(A‾∣x)=1P(A|x) + P(\overline{A}|x) = 1P(A∣x)+P(A∣x)=1。

[0,1]区间,和为1

输出oi∈[0,1]o_i \in [0,1]oi∈[0,1] ,且所有的输出值的和为1,这种设定以多分类问题最为常见(也适用于二分类)。输出层的每个输出节点代表了一种类别,且满足所有节点(类别)之间的概率和为1。

可以通过在输出层添加Softmax函数,Softmax 函数不仅可以将输出值映射到[0,1]区间,还满足所有的输出值之和为 1 的特性。Softmax函数定义为:Softmax(zi)≜ezi/∑j=1doutezjSoftmax(z_i) \triangleq e^{z_i}/\sum^{d_{out}}_{j=1}e^{z_j}Softmax(zi)≜ezi/∑j=1doutezj

在 TensorFlow 中,可以通过 tf.nn.softmax 实现 Softmax 函数:

python 复制代码
z = tf.constant([2.,1.,0.1])
tf.nn.softmax(z)

与 Dense 层类似,Softmax 函数也可以作为网络层类使用,通过类 layers.Softmax(axis=-1)可以方便添加 Softmax 层,其中 axis 参数指定需要进行计算的维度。

在 Softmax 函数的数值计算过程中,容易因输入值偏大发生数值溢出现象:在计算交叉熵时,也会出现数值溢出的问题。为了数值计算的稳定性,TensorFlow 中提供了一个统一的接口,将 Softmax 与交叉熵损失函数同时实现,同时也处理了数值不稳定的异常,一般推荐使用这些接口函数,避免分开使用 Softmax 函数与交叉熵损失函数。

函数式接口为tf.keras.losses.categorical_crossentropy(y_true, y_pred, from_logits=False),其中 y_true 代表了One-hot 编码后的真实标签,y_pred 表示网络的预测值,当 from_logits 设置为 True 时,y_pred 表示须为未经过 Softmax 函数的变量 z;当 from_logits 设置为 False 时,y_pred 表示为经过 Softmax 函数的输出。为了数值计算稳定性,一般设置 from_logits 为 True,此时tf.keras.losses.categorical_crossentropy 将在内部进行 Softmax 函数计算,所以不需要在模型中显式调用 Softmax 函数:

python 复制代码
z = tf.random.normal([2,10])
y_onehot = tf.constant([1,3])
y_onehot = tf.one_hot(y_onehot,depth=10)
loss = keras.losses.categorical_crossentropy(y_onehot,z,from_logits=True)
loss = tf.reduce_mean(loss) # 计算平均交叉熵损失

也可以利用 losses.CategoricalCrossentropy(from_logits)类方式同时实现 Softmax 与交叉熵损失函数的计算:

python 复制代码
criteon = keras.losses.CategoricalCrossentropy(from_logits=True)
loss = criteon(y_onehot,z) # 计算损失

[-1,1]

如果希望输出值的范围分布在(−1,1)区间,可以简单地使用 tanh 激活函数:

python 复制代码
x = tf.linspace(-6,6,120)
tf.tanh(x) # tanh 激活函数

误差计算

在搭建完模型结构后,下一步就是选择合适的误差函数来计算误差。常见的误差函数有均方差、交叉熵、KL 散度、Hinge Loss 函数等,其中均方差函数和交叉熵函数在深度学习中比较常见,均方差函数主要用于回归问题,交叉熵函数主要用于分类问题。

均方差误差函数

均方差(MSE)误差函数把输出向量和真实向量映射到笛卡尔坐标系的两个点上,通过计算这两个点之间的欧式距离(准确地说是欧式距离的平方)来衡量两个向量之间的差距:MSE(y,0)≜1dout∑i=1dout(yi−oi)2MSE(y,0)\triangleq \frac{1}{d_{out}}\sum_{i=1}^{d_{out}}(y_i-o_i)^2MSE(y,0)≜dout1∑i=1dout(yi−oi)2

MSE 误差函数的值总是大于等于 0,当 MSE 函数达到最小值 0 时,输出等于真实标签,此时神经网络的参数达到最优状态。

均方差误差函数广泛应用在回归问题中,实际上,分类问题中也可以应用均方差误差函数。在 TensorFlow 中,可以通过函数方式或层方式实现 MSE 误差计算。

python 复制代码
o = tf.random.normal([2,10])
y_onehot = tf.constant([1,3])
y_onehot = tf.one_hot(y_onehot,depth=10)
loss = keras.losses.MSE(y_onehot,o) #计算每个样本的均方差
loss = tf.reduce_mean(loss) # 收敛计算整体的均方误差

交叉熵误差函数

信息学中熵(Entropy)的概念:将热力学中熵的概念引入到信息论中,用来衡量信息的不确定度。熵在信息学科中也叫信息熵,或者香农熵。熵越大,代表不确定性越大,信息量也就越大。

某个分布𝑃(𝑖)的熵定义为:H(P)≜−∑iP(i)long2P(i)H(P) \triangleq - \sum_{i}P(i)long_2P(i)H(P)≜−∑iP(i)long2P(i) ;实际上,𝐻(𝑃)也可以使用其他底数的log函数计算。

由于𝑃(𝑖)∈[0,1],long2𝑃(𝑖)≤0𝑃(𝑖) \in [0,1], long_2𝑃(𝑖) ≤ 0P(i)∈[0,1],long2P(i)≤0,因此熵𝐻(𝑃)总是大于等于 0。当熵取得最小值 0 时,不确定性为 0。分类问题的 One-hot 编码的分布就是熵为 0 的典型例子。在 TensorFlow 中间,我们可以利用 tf.math.log 来计算熵。

......

最小化交叉熵损失函数的过程是最大化正确类别的预测概率的过程

神经网络类型

卷积神经网络

全连接层在处理高维度的图片、视频数据时往往出现网络参数量巨大,训练非常困难的问题。通过利用局部相关性和权值共享的思想,Yann Lecun 在 1986 年提出了卷积神经网络(CNN)。随着深度学习的兴盛,卷积神经网络在计算机视觉中的表现大大地超越了其它算法模型,呈现统治计算机视觉领域之势。

循环神经网络

循环神经网络(RNN),非常擅长处理序列信号(序列信号也是非常常见的一种数据类型,其中一个最具代表性的序列信号就是文本数据),在自然语言处理中得到了广泛的应用。

注意力(机制)网络

RNN 并不是自然语言处理的最终解决方案,注意力机制的提出,克服了 RNN 训练不稳定、难以并行化等缺陷,在自然语言处理和图片生成等领域中逐渐崭露头角。

图卷积神经网络

图片、文本等数据具有规则的空间、时间结构,称为 Euclidean Data(欧几里德数据)。卷积神经网络和循环神经网络被证明非常擅长处理这种类型的数据。而像类似于社交网络、通信网络、蛋白质分子结构等一系列的不规则空间拓扑结构的数据,它们显得力不从心。Thomas Kipf 等人基于前人在一阶近似的谱卷积算法上提出了图卷积网络(GCN)。GCN 算法实现简单,从空间一阶邻居信息聚合的角度也能直观地理解,在半监督任务上取得了不错效果。

相关推荐
AngelPP12 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年12 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼12 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS13 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区14 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈14 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang14 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx
shengjk116 小时前
NanoClaw 深度剖析:一个"AI 原生"架构的个人助手是如何运转的?
人工智能
西门老铁17 小时前
🦞OpenClaw 让 MacMini 脱销了,而我拿出了6年陈的安卓机
人工智能