神经网络识别猫图形

阅读: 评论:0

神经网络识别猫图形

神经网络识别猫图形

使用二层和四层神经网络分类图片

目的:判断一张图片是否是猫。查看两层和四层的区别

1.编写获取数据函数

def load_data():train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r")train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # your train set featurestrain_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labelstest_dataset = h5py.File('datasets/test_catvnoncat.h5', "r")test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set featurestest_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labelsclasses = np.array(test_dataset["list_classes"][:]) # the list of classestrain_set_y_orig = train_set_shape((1, train_set_y_orig.shape[0]))#(1,m) 二维数组表示行向量 test_set_y_orig = test_set_shape((1, test_set_y_orig.shape[0]))return train_set_x_orig, train_set_y_orig,test_set_x_orig, test_set_y_orig, classes#加载原始数据集
train_x_orig,train_y,test_x_orig,test_y,classes = load_data()
  • 可视化某一张图片 25

#可视化某一张图片
index=25
plt.imshow(train_x_orig[index]) #可视化原始训练集中第index+1张图片
print("y = "+str(train_y[0,index])+". It is a "+classes[train_y[0,index]].decode("utf-8")+" picture.")

  • 查看原始数据集形状

m_train = train_set_y.shape[1] #训练集里图片的数量。
m_test = test_set_y.shape[1] #测试集里图片的数量。
num_px = train_set_x_orig.shape[1] #训练、测试集里面的图片的宽度和高度(均为64x64)。
#现在看一看我们加载的东西的具体情况
print ("训练集的数量: m_train = " + str(m_train))
print ("测试集的数量 : m_test = " + str(m_test))
print ("每张图片的宽/高 : num_px = " + str(num_px))
print ("每张图片的大小 : (" + str(num_px) + ", " + str(num_px) + ", 3)")
print ("训练集_图片的维数 : " + str(train_set_x_orig.shape))
print ("训练集_标签的维数 : " + str(train_set_y.shape))
print ("测试集_图片的维数: " + str(test_set_x_orig.shape))
print ("测试集_标签的维数: " + str(test_set_y.shape))
==========================================训练集的数量: m_train = 209
测试集的数量 : m_test = 50
每张图片的宽/高 : num_px = 64
每张图片的大小 : (64, 64, 3)
训练集_图片的维数 : (209, 64, 64, 3)
训练集_标签的维数 : (1, 209)
测试集_图片的维数: (50, 64, 64, 3)
测试集_标签的维数: (1, 50)

  • 数据集预处理

在此之后,训练和测试数据集是一个numpy数组,【每列代表一个平坦的图像】 ,应该有m_train和m_test列
当想将形状(a,b,c,d)的矩阵X平铺成形状(b * c * d,a)的矩阵X_flatten时,可以使用以下代码:


#对训练集和测试集中的图片进行转型
train_x_flatten=train_shape(m_train,-1).T #训练集图片的特征矩阵 (num_px*num_px*3,m_train) 每一列为一张图片的拉伸后的特征向量
test_x_flatten=test_shape(m_test,-1).T #测试集图片的特征矩阵 (num_px*num_px*3,m_test) 每一列为一张图片的拉伸后的特征向量
  • 数据标准化
#对图片的特征矩阵进行标准化 除以最大值255 使特征数值在0-1之间
train_x=train_x_flatten/255
test_x=test_x_flatten/255print ("train_x's shape: " + str(train_x.shape))
print ("test_x's shape: " + str(test_x.shape))

将使用两种神经网络进行训练

1. 双层神经网络(L=2 单隐层)
2. L层的神经网络(L>=3 隐层数>=2)

一. 双层神经网络


1.构建神经网络步骤

  • 初始化模型参数(随机)/定义模型超参数
  • 梯度下降迭代步骤
  • 向前
  • 计算代价
  • 反向
  • 计算梯度
  • 更新参数

**

构建双层神经网络(L = 2 ,单隐层)

**

linear>relu>linear>sigmoid

  • 随机初始化模型参数(高斯分布)*0.01
def initialize_parameters(n_x,n_h,n_y):'''初始化双层神经网络的参数参数:n_x:输入层单元数 取决于输入样本的特征向量维数n_h:隐层单元数 可以任意设置n_y:输出层单元数 n_y=1返回:parameters:初始化后的参数(字典形式)W1:(n_h,n_x)b1:(n_h,1)W2:(n_y,n_h)b2:(n_y,1)'''W1=np.random.randn(n_h,n_x)*0.01b1&#s((n_h,1))W2=np.random.randn(n_y,n_h)*0.01b2&#s((n_y,1))assert(W1.shape == (n_h,n_x))assert(b1.shape == (n_h, 1))assert(W2.shape == (n_y, n_h))assert(b2.shape == (n_y, 1))parameters = {"W1": W1,"b1": b1,"W2": W2,"b2": b2}return parameters     
  1. 向前传播
  2. 以下定义的前向传播是在某一层上的前向传播 不是总体的前向传播
    对于浅层神经网络 总体的前向传播可以一层层写出来 也可以用for循环
    对于深层神经网络 总体的前向传播用for循环迭代单层的前向传播 直到最后的输出,当然也可以一层层的写

1.线性向前运算代码实现
公式: Z = W T ∗ X + b Z = W^T*X +b Z=WT∗X+b

def linear_forward(A,W,b):'''隐层/输出层 前向传播的线性组合部分参数:A:上一层的激活函数输出 初始值是样本特征矩阵XW:当前层的权重参数矩阵b: 当前层的偏置参数向量返回:Z:当前层的线性组合输出cache:元组形式 (A,W,b)'''Z = np.dot(W,A)+bassert(Z.shape == (W.shape[0],A.shape[1]))cache = (A,W,b) return Z,cache

2.前向激活函数代码实现


def sigmoid(Z):'''2分类,输出层采用sigmoid激活函数输出层前向传播的激活函数部分参数:Z:当前层(输出层)的线性组合输出返回:A:当前层(输出层)的激活输出cache: Z'''A = 1./(1&#p(-Z))cache = Zassert(A.shape == Z.shape)return A,cachedef relu(Z):'''隐层统一采用relu激活函数参数:Z:当前层(隐层)的线性组合输出返回:A:当前层(隐层)的激活输出cache: Z'''A = np.maximum(0,Z)cache = Zassert(A.shape == Z.shape)return A,cachedef linear_activation_forward(A_prev,W,b,activation):'''隐层(输出层)的前向传播操作,包括线性组合和激活函数两部分参数:A_perv:上一层的激活函数输出 初始值是样本特征矩阵XW:上一层和当前层之间的权重参数矩阵b: 上一层和当前层之间的偏置参数向量activation:使用的激活函数类型 一般所有隐层的激活函数是一样的 输出层如果作2分类使用sigmoid返回:A: 当前层的激活函数输出cache:存储重要的中间结果,方便运算。元组形式(linear_cache,activation_cache)=((A_prev,W,b),Z)'''if activation == 'sigmoid':Z,linear_cache = linear_forward(A_prev,W,b) #线性单元A,activation_cache = sigmoid(Z)  #激活单元elif activation == 'relu':Z,linear_cache = linear_forward(A_prev,W,b) #线性单元A,activation_cache = relu(Z)  #激活单元assert(A.shape == (W.shape[0],A_prev.shape[1]))cache=(linear_cache,activation_cache)return A,cache

3.计算损失值

def compute_cost(AL,Y):'''实现cost函数,计算代价参数:AL:输出层的激活输出 模型最终输出 (1,m)Y:样本的真实标签 0/1 (1,m)返回:cost: 交叉熵代价'''cost = np.mean(-Y*np.log(AL)-(1-Y)*np.log(1-AL))cost = np.squeeze(cost) #Y和AL都是用2维数组表示的向量 cost算出来是[[cost]],利用squeeze把它变成costassert(cost.shape == ()) return cost

更新梯度

def update_parameters(parameters,grads,learning_rate):'''使用梯度下降法更新模型参数参数:parameters:模型参数grads:计算的参数梯度 字典形式learning_rate:学习率返回:parameters:更新后的参数 字典形式parameters["W" + str(l)] = ... parameters["b" + str(l)] = ...'''L = len(parameters)//2 #神经网络层数(输入层是第0层 不算输入层)#一次梯度下降迭代 更新参数for l in range(L):  #l 0~L-1parameters['W'+str(l+1)] = parameters['W'+str(l+1)] - learning_rate*grads['dW'+str(l+1)]parameters['b'+str(l+1)] = parameters['b'+str(l+1)] - learning_rate*grads['db'+str(l+1)]return parameters

4.构建双层神经网络模型


#定义网络结构
n_x = 12288 #num_px*num_px*3
n_h = 7  #隐层单元数 可以设置
n_y = 1 #2分类layers_dims = (n_x,n_h,n_y)  #各层单元数
def two_layer_model(X,Y,layers_dims,learning_rate=0.0075,num_iterations=3000,print_cost=False):'''实现双层网络结构参数:X:训练集特征矩阵 (n_x,m_train) Y:训练集样本对于的标签 0/1 (1,m_train)layers_dims:各层的单元数learning_rate:学习率num_iterations:梯度下降法迭代次数print_cost:为True时,每100次迭代打印一次cost返回:parameters:训练好的参数 字典形式parameters["W" + str(l)] = ... parameters["b" + str(l)] = ...'''np.random.seed(1)grads = {} #存储每一次反向传播计算的梯度costs = [] #存储每100次前向传播计算的代价m = X.shape[1](n_x,n_h,n_y) = layers_dims#初始化模型参数parameters = initialize_parameters(n_x,n_h,n_y)#取出每一个初始化后的参数W1 = parameters['W1']b1 = parameters['b1']W2 = parameters['W2']b2 = parameters['b2']#梯度下降迭代#batch GD 每一次使用全部的样本计算梯度for i in range(num_iterations):#前向传播A1,cache1 = linear_activation_forward(X,W1,b1,'relu')A2,cache2 = linear_activation_forward(A1,W2,b2,'sigmoid')#计算代价cost = compute_cost(A2,Y)#计算反向传播的初始项 dAL=dA2dA2 = -Y/A2 + (1-Y)/(1-A2)dA1,dW2,db2 = linear_activation_backward(dA2,cache2,'sigmoid')dA0,dW1,db1 = linear_activation_backward(dA1,cache1,'relu')grads['dW1']=dW1grads['db1']=db1grads['dW2']=dW2grads['db2']=db2#更新参数parameters = update_parameters(parameters,grads,learning_rate)#取出每一个更新后的参数W1 = parameters['W1']b1 = parameters['b1']W2 = parameters['W2']b2 = parameters['b2']#每100次迭代打印一次代价 并存储if print_cost and i%100==0:print("Cost after iteration {}: {}".format(i, np.squeeze(cost)))costs.append(cost)#绘制代价对迭代次数的变化曲线plt.plot(np.squeeze(costs))plt.ylabel('cost')plt.xlabel('iterations (per hundreds)')plt.title("Learning rate =" + str(learning_rate))plt.show()return parameters
  • 训练双层网络

parameters = two_layer_model(train_x, train_y, layers_dims = (n_x, n_h, n_y), num_iterations = 2500, print_cost=True)

  • 编写预测函数代码

  • 上一步中的optimize函数会输出已学习的w和b的值,我们可以使用w和b来预测数据集X的标签。

  • 计算预测步骤:

    • p [ A 2 > 0.5 ] = 1 p[A2 > 0.5] = 1 p[A2>0.5]=1
def predict(X,Y,parameters):'''使用训练好的模型进行预测参数:X:数据集样本特征矩阵(n_x,m)Y:数据集样本真实标签 0/1 (1,m)parameters:训练好的参数返回:p:数据集样本预测标签 0/1'''#取出每一个学习好的的参数W1 = parameters['W1']b1 = parameters['b1']W2 = parameters['W2']b2 = parameters['b2']#前向传播  linear_activation_forward定义了一层的前向传播A1,cache1 = linear_activation_forward(X,W1,b1,'relu')A2,cache2 = linear_activation_forward(A1,W2,b2,'sigmoid')m = X.shape[1]p = np.zeros((1,m))p[A2 > 0.5] = 1print("Accuracy: "  + an(p == Y)))return p

predictions_train = predict(train_x, train_y, parameters) #训练集上的准确率predictions_test = predict(test_x, test_y, parameters)#测试集上的准确率
  • 对两层神经网络进行照片预测
index = 32
plt.imshow(test_x[:,index].reshape((64, 64, 3)))
print ("y = " + str(test_set_y[0,index]) + ", you predicted that it is a "" + classes[int(predictions_test[0,index])].decode("utf-8") +  "" picture.")

二. L层神经网络(L>=3,隐藏层数 >= 2)


构建L层神网络

网络结构: [linear>relu]x(L-1)>linear>sigmoid

  • 随机初始化参数:选择he初始化
def initialize_parameters_deep(layer_dims):'''参数:layer_dims:网络每一层的单元数返回:parameters:初始化后的参数 字典形式"W1", "b1", ..., "WL", "bL":Wl -- weight matrix of shape (layer_dims[l], layer_dims[l-1])bl -- bias vector of shape (layer_dims[l], 1)'''np.random.seed(1)parameters = {}L = len(layer_dims) #神经网络层数+1 包括输入层for l in range(1,L):parameters['W'+str(l)] = np.random.randn(layer_dims[l],layer_dims[l-1])*np.sqrt(2./layer_dims[l-1]) #*0.01parameters['b'+str(l)] = np.zeros((layer_dims[l],1))assert(parameters['W' + str(l)].shape == (layer_dims[l], layer_dims[l-1]))assert(parameters['b' + str(l)].shape == (layer_dims[l], 1))return parameters

注意:由于隐藏层统一同relu激活函数,输出层2分类用的是sigmoid,隐藏层可以统一处理,输出层单独处理

  • ** L层网络前向传播**

#之前定义了每层的前向传播 对于深层网络来说整体的前向传播 可以使用for循环迭代每层的前向传播def linear_forward(A,W,b):'''隐层/输出层 前向传播的线性组合部分参数:A:上一层的激活函数输出 初始值是样本特征矩阵XW:当前层的权重参数矩阵b: 当前层的偏置参数向量返回:Z:当前层的线性组合输出cache:元组形式 (A,W,b)'''Z = np.dot(W,A)+bassert(Z.shape == (W.shape[0],A.shape[1]))cache = (A,W,b) return Z,cachedef sigmoid(Z):'''2分类,输出层采用sigmoid激活函数输出层前向传播的激活函数部分参数:Z:当前层(输出层)的线性组合输出返回:A:当前层(输出层)的激活输出cache: Z'''A = 1./(1&#p(-Z))cache = Zassert(A.shape == Z.shape)return A,cachedef relu(Z):'''隐层统一采用relu激活函数参数:Z:当前层(隐层)的线性组合输出返回:A:当前层(隐层)的激活输出cache: Z'''A = np.maximum(0,Z)cache = Zassert(A.shape == Z.shape)return A,cachedef linear_activation_forward(A_prev,W,b,activation):'''隐层(输出层)的前向传播操作,包括线性组合和激活函数两部分参数:A_perv:上一层的激活函数输出 初始值是样本特征矩阵XW:上一层和当前层之间的权重参数矩阵b: 上一层和当前层之间的偏置参数向量activation:使用的激活函数类型 一般所有隐层的激活函数是一样的 输出层如果作2分类使用sigmoid返回:A: 当前层的激活函数输出cache:存储重要的中间结果,方便运算。元组形式(linear_cache,activation_cache)=((A_prev,W,b),Z)'''if activation == 'sigmoid':Z,linear_cache = linear_forward(A_prev,W,b) #线性单元A,activation_cache = sigmoid(Z)  #激活单元elif activation == 'relu':Z,linear_cache = linear_forward(A_prev,W,b) #线性单元A,activation_cache = relu(Z)  #激活单元assert(A.shape == (W.shape[0],A_prev.shape[1]))cache=(linear_cache,activation_cache)return A,cachedef L_model_forward(X,parameters):'''L层神经网络整体的前向传播 调用之前写好的每层的前向传播 用for循环迭代参数:X:数据集的特征矩阵 (n_x,m)parameters:模型参数返回:AL:模型最后的输出caches:列表形式,存储每一层前向传播的cache=(linear_cache,activation_cache)=((A_prev,W,b),Z)  对于linear_relu_forward()有L-1项cache  下标0~L-2对于linear_sigmoid_forward()有1项cache  下标L-1'''caches = []A = X  #A0  前向传播初始项L = len(parameters)//2 #神经网络层数(不包含输入层)#前向传播通项#隐层和输出层激活函数不同 for循环迭代隐层前向传播 输出层前向传播单独算#隐层for l in range(1,L): #l: 1~L-1 A_prev = AA,cache = linear_activation_forward(A_prev,parameters['W'+str(l)],parameters['b'+str(l)],'relu')caches.append(cache)#输出层AL,cache = linear_activation_forward(A,parameters['W'+str(L)],parameters['b'+str(L)],'sigmoid')caches.append(cache)return AL,caches
  • 计算损失函数
def compute_cost(AL,Y):'''实现cost函数,计算代价参数:AL:输出层的激活输出 模型最终输出 (1,m)Y:样本的真实标签 0/1 (1,m)返回:cost: 交叉熵代价'''cost = np.mean(-Y*np.log(AL)-(1-Y)*np.log(1-AL))cost = np.squeeze(cost) #Y和AL都是用2维数组表示的向量 cost算出来是[[cost]],利用squeeze把它变成costassert(cost.shape == ()) return cost
  • 反向传播计算梯度
def sigmoid_backward(dA,cache):'''sigmoid激活单元(输出层)的反向传播参数:dA:当前层(输出层)激活输出AL的梯度cache:存储当前层(输出层)的线性组合输出Z,方便激活单元反向传播的计算返回:dZ:当前层(输出层)线性组合输出Z的梯度'''Z = caches = 1./(1&#p(-Z))#dZ=dA*(A对Z求导) A=sigmoid(Z) A对Z的导数=A(1-A)dZ = dA*s*(1-s) assert(dZ.shape == Z.shape)return dZdef relu_backward(dA,cache):'''隐层统一使用relu激活函数relu激活单元(隐层)的反向传播参数:dA:当前层(隐层)激活输出Al的梯度cache:存储当前层(隐层)的线性组合输出Z,方便激活单元反向传播的计算返回:dZ:当前层(隐层)线性组合输出Z的梯度'''Z = cache#dZ=dA*(A对Z求导) 当Z>0时 A对Z求导=1 否则为0dZ = np.array(dA,copy=True)dZ[Z<=0] = 0assert(dZ.shape == Z.shape)return dZdef linear_backward(dZ,cache):'''输出层/隐层 线性单元的反向传播参数:dZ:当前层组合输出Z的梯度cache:存储当前层前向传播的线性单元参数 (A_prev,W,b),方便线性单元反向传播的计算返回:dA_prev:前一层激活输出的梯度dW:当前层权重参数矩阵的梯度db:当前层偏置参数向量的梯度'''A_prev,W,b = cachem = A_prev.shape[1] #样本数dW = 1./m*np.dot(dZ,A_prev.T) #m个样本的平均梯度db = np.mean(dZ,axis=1,keepdims=True)dA_prev = np.dot(W.T,dZ)assert(dW.shape == W.shape)assert(db.shape == b.shape)assert(dA_prev.shape == A_prev.shape)return dA_prev,dW,db
def linear_activation_backward(dA,cache,activation):"""输出层隐层的反向传播操作,包括激活函数和线性组合两部分dvar 代表 最终输出对var的偏导参数:dA:当前层的激活输出梯度dAl 初始值是dAL (代价函数对AL求偏导)cache:前向传播阶段存储的重要参数和中间结果,便于与反向传播共享参数,方便运算。元组形式(linear_cache,activation_cache)=((A_prev,W,b),Z)activation:使用的激活函数类型 一般所有隐层的激活函数是一样的 输出层如果作2分类使用sigmoid返回:dA_prev:前一层激活输出的梯度dA(l-1)dW:当前层权重矩阵的梯度 和当前层W维度一致db:当前层偏置向量的梯度 和当前层b维度一致"""linear_cache,activation_cache = cacheif activation == 'sigmoid':dZ = sigmoid_backward(dA,activation_cache) #激活单元反向传播dA_prev,dW,db = linear_backward(dZ,linear_cache)#线性单元反向传播elif activation == 'relu':dZ = relu_backward(dA,activation_cache) #激活单元反向传播dA_prev,dW,db = linear_backward(dZ,linear_cache)#线性单元反向传播return dA_prev,dW,db#向后传播模型
def L_model_backward(AL,Y,caches):'''L层神经网络整体的反向传播 调用之前写好的每层的反向传播 用for循环迭代参数:AL:前向传播最终的输出Y:数据集样本真实标签 0/1caches:前向传播缓存的重要参数和中间结果 方便运算列表形式,存储每一层前向传播的cache=(linear_cache,activation_cache)=((A_prev,W,b),Z)  对于linear_relu_forward()有L-1项cache  下标0~L-2对于linear_sigmoid_forward()有1项cache  下标L-1返回:grads:字典形式 存储每一层参数的梯度:grads["dA" + str(l)] = ... grads["dW" + str(l)] = ...grads["db" + str(l)] = ... '''grads = {}L = len(caches) #网络层数 不包含输入层m = AL.shape[1]Y = Y.reshape(AL.shape)#反向传播初始项dAL = -Y/AL + (1-Y)/(1-AL)#输出层单独计算 隐层统一用for循环计算current_cache = caches[L-1] #输出层前向传播的cachegrads['dA'+str(L)],grads['dW'+str(L)],grads['db'+str(L)] = linear_activation_backward(dAL,current_cache,'sigmoid') #grads['dAl']实际上是grads['dAl-1'] 便于与dW,db统一处理for l in reversed(range(L-1)): #l:L-2~0current_cache = caches[l]dA_prev_temp, dW_temp, db_temp = linear_activation_backward(grads['dA'+str(l+2)],current_cache,'relu')grads["dA" + str(l + 1)] = dA_prev_tempgrads["dW" + str(l + 1)] = dW_tempgrads["db" + str(l + 1)] = db_tempreturn grads
  • 更新参数
def update_parameters(parameters,grads,learning_rate):'''使用梯度下降法更新模型参数参数:parameters:模型参数grads:计算的参数梯度 字典形式learning_rate:学习率返回:parameters:更新后的参数 字典形式parameters["W" + str(l)] = ... parameters["b" + str(l)] = ...'''L = len(parameters)//2 #神经网络层数(输入层是第0层 不算输入层)#一次梯度下降迭代 更新参数for l in range(L):  #l 0~L-1parameters['W'+str(l+1)] = parameters['W'+str(l+1)] - learning_rate*grads['dW'+str(l+1)]parameters['b'+str(l+1)] = parameters['b'+str(l+1)] - learning_rate*grads['db'+str(l+1)]return parameters
#定义网络结构
layers_dims = [12288, 20, 7, 5, 1] # 各层的单元数 四层网
  • 整合模型
def L_layer_model(X, Y, layers_dims, learning_rate = 0.0075, num_iterations = 3000, print_cost=False):'''实现L层网络参数:X:训练集样本特征矩阵(n_x,m_train)Y:训练集样本标签 0/1 (1,m_train)layers_dims:各层的单元数learning_rate:学习率num_iterations:梯度下降法迭代次数print_cost:为True时,每100次迭代打印一次cost返回:parameters:训练好的参数 字典形式parameters["W" + str(l)] = ... parameters["b" + str(l)] = ...'''np.random.seed(1)costs = [] #存储每100次前向传播计算的代价#初始化参数parameters = initialize_parameters_deep(layers_dims)#梯度下降迭代#batch GD 每次反向传播使用全部样本计算梯度for i in range(num_iterations):#前向传播AL,caches = L_model_forward(X,parameters)#计算代价cost = compute_cost(AL,Y)#反向传播计算梯度grads = L_model_backward(AL,Y,caches)#更新参数parameters = update_parameters(parameters,grads,learning_rate)#每100次迭代打印一次代价 并存储if print_cost and i%100==0:print("Cost after iteration {}: {}".format(i, np.squeeze(cost)))costs.append(cost)#绘制代价对迭代次数的变化曲线plt.plot(np.squeeze(costs))plt.ylabel('cost')plt.xlabel('iterations (per hundreds)')plt.title("Learning rate =" + str(learning_rate))plt.show()return parameters

下一篇我们会给此4层神经网络加入:L2正则,dropout,,mini_batch—MBGD(小批量梯度下降),(Momentum、adam)优化器。

此文章借鉴与:.L%E5%B1%82%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C(L%3E%3D3%2C%E9%9A%90%E5%B1%82%E6%95%B0%3E%3D2)

本文发布于:2024-02-04 16:48:37,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170712029757487.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:神经网络   猫图
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23