游戏AI的创造思路-技术基础-深度学习(1)

他来了,他来啦,后面歌词忘了~~~~~

开谈深度学习,填上一点小坑,可又再次开掘大洞 -.-b

目录

1. 定义

2. 深度学习的发展历史和典型事件

3. 深度学习常用算法

3.1. 卷积神经网络(CNN)

3.1.1. 算法形成过程与运行原理

3.1.1.1. 基本结构

3.1.1.2. 前向传播算法

3.1.1.3. 前向传播算法示例-图像预处理

3.1.1.4. 前向传播算法示例-卷积计算

3.1.1.5. 前向传播算法示例-池化操作

3.1.1.6. 前向传播算法示例-全连接层处理

3.1.1.7. 前向传播算法示例-输出层

3.1.2. 整体算法示例

3.2. 循环神经网络(RNN)

3.3. 长短期记忆网络(LSTM)

3.4. 生成对抗网络(GAN)

3.5. 自编码器(AE)

3.6. 深度信念网络(DBN)

3.7. Transformer


1. 定义

深度学习(Deep Learning)是机器学习的一个子领域,它依赖于神经网络的结构。

深度学习通过组合低层特征形成更加抽象的高层表示属性类别或特征,以发现数据的分布式特征表示。

简单来说,深度学习是学习样本数据的内在规律和表示层次,这些学习过程中获得的信息对诸如文字,图像和声音等数据的解释有很大的帮助。

它的最终目标是让机器能够识别和解释各种数据,如文字、图像和声音等,从而实现人工智能的目标。

传统的机器学习技术相比,深度学习可以自动提取数据的特征,而无需人工设计和选择特征。

这一特点使得深度学习在处理复杂和大规模的数据时具有显著的优势。

通过深度学习,机器可以模仿人类的视听和思考等活动(假装他是一个人类,其实谁还不是个宝宝),解决复杂的模式识别难题。

2. 深度学习的发展历史和典型事件

深度学习发展也算是历史老玩家了,其可以大致归纳为以下几个阶段:

  1. 萌芽期(20世纪40年代至80年代):深度学习的概念起源于20世纪40年代,当时神经科学家Warren McCulloch和数学家Walter Pitts提出了神经网络的概念。在20世纪50年代,心理学家Frank Rosenblatt提出了感知机的概念,这是最早的深度学习模型之一。然而,由于当时计算机科学的限制和数据的不足,深度学习的发展受到了制约。

  2. 起步期(20世纪80年代至90年代):随着计算机科学的飞速发展,人工神经网络的研究和应用得到了推动。这个时期出现了许多著名的深度学习模型,如反向传播算法和卷积神经网络等,这些模型逐渐涉及到图像识别、语音识别和自然语言处理等领域。

  3. 发展期(20世纪90年代至2010年):随着互联网的普及和数据的增加,深度学习逐渐得到了更多的关注和研究。出现了许多重要的深度学习模型和技术,如堆叠式自编码器、循环神经网络和长短时记忆网络等。这些模型的应用范围不断扩大,涉及到自然语言处理、语音识别和计算机视觉等领域。

  4. 成熟期(2011年至今):从2011年开始,深度学习进入了成熟期,出现了许多重要的研究成果和技术创新,如批量标准化、残差网络和注意力机制等。这些技术和方法的应用使得深度学习在许多领域中都取得了显著的进展,如自然语言处理、计算机视觉和医疗诊断等。

3. 深度学习常用算法

在深度学习领域,常用的算法包括:

3.1. 卷积神经网络(CNN)

卷积神经网络(Convolutional Neural Networks, CNNs)是深度学习中的一种重要模型,特别适用于图像处理和和视频、层级结构数据等具有网格结构的数据,在图像识别、物体检测和视频分析等领域有广泛应用。

3.1.1. 算法形成过程与运行原理
3.1.1.1. 基本结构
  • 卷积神经网络的基本结构包括卷积层、池化层和全连接层。
  • 卷积层用于提取特征,通过多组卷积核与输入图像进行卷积运算,得到不同的特征图。
  • 池化层进行降采样操作,降低特征图的分辨率,减少模型的计算复杂度,并有效避免过拟合。
  • 全连接层将卷积层和池化层输出的特征图转化为分类结果。
3.1.1.2. 前向传播算法
  • 图像预处理:包括图像归一化、色彩空间转换等操作。
  • 卷积计算:将处理后的图像送入卷积层,通过卷积核进行特征提取。卷积计算可用公式表示:    (f_{i,j}=\sum_{m=0}{k-1}\sum_{n=0}{k-1}x_{i+m,j+n}w_{m,n}+b)                              其中(f_{i,j}) 是卷积输出结果,(x_{i+m,j+n}) 是图像中的值,(w_{m,n})是卷积核权重,(b)是偏置。
  • 池化操作:对卷积后的特征图进行降采样,通常使用最大值池化或平均值池化。
  • 全连接层处理:池化后的结果送入全连接层,通过权重矩阵和偏置进行处理,产生输出结果。
  • 输出层:通常使用softmax函数估计不同类别的概率。
3.1.1.3. 前向传播算法示例-图像预处理

前向传播算法中的图像预处理通常包括图像的归一化、色彩空间的转换、裁剪、缩放等操作,以便使图像数据适应神经网络模型的输入要求。下面分别给出Python和C++的图像预处理示例。

Python 示例

在Python中,我们通常使用OpenCVPIL(Python Imaging Library,现在称为Pillow)等库来进行图像预处理。以下是一个使用Pillow进行图像预处理的简单示例:

from PIL import Image  
import numpy as np  
  
# 加载图像  
image_path = 'path_to_your_image.jpg'  
image = Image.open(image_path)  
  
# 缩放图像到指定大小(例如:224x224)  
resized_image = image.resize((224, 224))  
  
# 将图像转换为numpy数组  
image_array = np.array(resized_image)  
  
# 归一化图像数据到[0, 1]范围  
normalized_image = image_array / 255.0  
  
# 如果需要,可以将图像数据转换为浮点型  
normalized_image = normalized_image.astype(np.float32)  
  
# 如果模型需要,可以扩展图像维度以匹配模型的输入形状(例如:添加批次维度和通道维度)  
preprocessed_image = np.expand_dims(normalized_image, axis=0)  # 添加批次维度  
if len(preprocessed_image.shape) == 3:  
    preprocessed_image = np.expand_dims(preprocessed_image, axis=-1)  # 添加通道维度(对于灰度图)  
  
# 现在preprocessed_image可以作为神经网络的输入了

C++ 示例

在C++中,我们通常使用OpenCV库来进行图像预处理。以下是一个使用OpenCV进行图像预处理的简单示例:

#include <opencv2/opencv.hpp>  
#include <iostream>  
  
int main() {  
    // 读取图像  
    cv::Mat image = cv::imread("path_to_your_image.jpg");  
    if (image.empty()) {  
        std::cerr << "Could not open or find the image!" << std::endl;  
        return -1;  
    }  
  
    // 缩放图像到指定大小(例如:224x224)  
    cv::Mat resized_image;  
    cv::resize(image, resized_image, cv::Size(224, 224));  
  
    // 归一化图像数据到[0, 1]范围  
    resized_image.convertTo(resized_image, CV_32F, 1.0 / 255.0);  
  
    // 如果模型需要,可以调整图像矩阵的形状以匹配模型的输入(例如:添加批次维度)  
    // 在C++中,这通常不是必需的,因为你可以直接传递图像的原始数据指针给神经网络库  
  
    // 现在resized_image可以作为神经网络的输入了  
    // 通常,你会将resized_image的数据指针和形状信息传递给神经网络库进行处理  
  
    return 0;  
}

请注意,在实际应用中,你需要根据你的神经网络模型的输入要求来调整图像预处理步骤。例如,如果你的模型是在RGB色彩空间上训练的,那么你需要确保输入的图像也是RGB格式的。

此外,如果你的模型期望的输入是特定的数据布局(例如,“批次大小 x 通道数 x 高度 x 宽度”),你可能需要在传递图像数据给模型之前对其进行相应的重塑或转换。

3.1.1.4. 前向传播算法示例-卷积计算

前向传播算法中的卷积计算是卷积神经网络(CNN)的核心操作之一。下面分别给出Python和C++中进行卷积计算的示例。

Python 示例

在Python中,我们通常使用深度学习框架如TensorFlow或PyTorch来进行卷积计算。以下是一个使用NumPy库手动实现卷积计算的简单示例:

import numpy as np  
  
def convolve2d(image, kernel):  
    # 获取图像和卷积核的尺寸  
    image_height, image_width = image.shape  
    kernel_height, kernel_width = kernel.shape  
      
    # 输出特征图的尺寸  
    output_height = image_height - kernel_height + 1  
    output_width = image_width - kernel_width + 1  
    output = np.zeros((output_height, output_width))  
      
    # 执行卷积操作  
    for i in range(output_height):  
        for j in range(output_width):  
            output[i, j] = np.sum(image[i:i+kernel_height, j:j+kernel_width] * kernel)  
      
    return output  
  
# 示例图像和卷积核  
image = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])  
kernel = np.array([[1, 0], [0, 1]])  
  
# 进行卷积计算  
feature_map = convolve2d(image, kernel)  
print(feature_map)

C++ 示例

在C++中,我们可以使用OpenCV库来进行卷积计算,或者手动实现卷积操作。以下是一个手动实现卷积计算的简单示例:

#include <iostream>  
#include <vector>  
  
std::vector<std::vector<double>> convolve2d(const std::vector<std::vector<double>>& image, const std::vector<std::vector<double>>& kernel) {  
    int image_height = image.size();  
    int image_width = image[0].size();  
    int kernel_height = kernel.size();  
    int kernel_width = kernel[0].size();  
      
    int output_height = image_height - kernel_height + 1;  
    int output_width = image_width - kernel_width + 1;  
    std::vector<std::vector<double>> output(output_height, std::vector<double>(output_width, 0));  
      
    for (int i = 0; i < output_height; ++i) {  
        for (int j = 0; j < output_width; ++j) {  
            for (int k = 0; k < kernel_height; ++k) {  
                for (int l = 0; l < kernel_width; ++l) {  
                    output[i][j] += image[i + k][j + l] * kernel[k][l];  
                }  
            }  
        }  
    }  
      
    return output;  
}  
  
int main() {  
    std::vector<std::vector<double>> image = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};  
    std::vector<std::vector<double>> kernel = {{1, 0}, {0, 1}};  
      
    std::vector<std::vector<double>> feature_map = convolve2d(image, kernel);  
      
    // 打印特征图  
    for (const auto& row : feature_map) {  
        for (double val : row) {  
            std::cout << val << " ";  
        }  
        std::cout << std::endl;  
    }  
      
    return 0;  
}

这两个示例分别展示了如何在Python和C++中手动实现二维卷积操作。

在实际应用中,我们通常会使用优化过的库函数来进行卷积计算,以提高性能和效率。

例如,在Python中可以使用scipy.signal.convolve2d函数,而在C++中可以使用OpenCV的filter2D函数。

3.1.1.5. 前向传播算法示例-池化操作

池化操作(Pooling)是卷积神经网络中常用的一种下采样技术,用于减少特征图的维度,同时保留重要特征。最常见的池化操作是最大池化(Max Pooling)和平均池化(Average Pooling)。

最大池化操作的公式可以表示为:对于输入特征图中的每个局部窗口,选择其中的最大值作为输出特征图对应位置的值。具体公式如下:

  • 定义局部窗口:设输入特征图为A,其尺寸为M x N。定义一个尺寸为k x k的池化窗口,其中k是池化核的大小。
  • 滑动窗口并选择最大值:池化窗口在输入特征图上以步长s滑动。在每个窗口位置,计算窗口内所有元素的最大值。具体计算可以用以下公式表示:

$y_{i,j}=\max_{m=0}^{k-1}\max_{n=0}^{k-1}x_{i+m,j+n}$

其中,( x_{i,j} )是输入特征图A中位置(i, j)的元素值,( y_{i,j} )是输出特征图中对应位置的值。这个公式表示在输入特征图上,以(is, js)为起点,取k * k窗口内的最大值作为输出。

  • 形成输出特征图:通过滑动窗口并计算每个窗口内的最大值,最终形成一个新的、尺寸较小的输出特征图。

需要注意的是,在实际应用中,池化操作的步长s和池化核大小k可以根据具体任务进行调整。最大池化操作能够减小特征图的尺寸,同时保留最重要的特征信息,有助于提升模型的鲁棒性和计算效率。

此外,对于边界处理,通常可以采用填充(padding)或者忽略边界区域的方式,以确保池化窗口能够在整个特征图上正确滑动。

以下是在Python和C++中执行最大池化操作的示例。

Python 示例

在Python中,我们通常使用深度学习框架如TensorFlow或PyTorch进行池化操作,但以下是一个使用NumPy手动实现最大池化的简单示例:

import numpy as np  
  
def max_pooling(feature_map, pool_size, stride):  
    # 获取特征图的尺寸  
    height, width = feature_map.shape  
      
    # 计算池化后的特征图尺寸  
    pooled_height = (height - pool_size) // stride + 1  
    pooled_width = (width - pool_size) // stride + 1  
    pooled_feature_map = np.zeros((pooled_height, pooled_width))  
      
    # 执行最大池化操作  
    for i in range(0, height - pool_size + 1, stride):  
        for j in range(0, width - pool_size + 1, stride):  
            patch = feature_map[i:i+pool_size, j:j+pool_size]  
            pooled_feature_map[i // stride, j // stride] = np.max(patch)  
      
    return pooled_feature_map  
  
# 示例特征图  
feature_map = np.array([  
    [1, 3, 2, 4],  
    [5, 6, 7, 8],  
    [9, 10, 11, 12],  
    [13, 14, 15, 16]  
])  
  
# 进行最大池化计算,池化窗口大小为2x2,步长为2  
pooled_map = max_pooling(feature_map, 2, 2)  
print(pooled_map)

C++ 示例

在C++中,我们可以使用OpenCV库中的cv::max函数辅助进行最大池化操作,或者手动实现。以下是一个手动实现最大池化的简单示例:

#include <iostream>  
#include <vector>  
#include <algorithm> // for std::max_element  
  
std::vector<std::vector<double>> max_pooling(const std::vector<std::vector<double>>& feature_map, int pool_size, int stride) {  
    int height = feature_map.size();  
    int width = feature_map[0].size();  
      
    int pooled_height = (height - pool_size) / stride + 1;  
    int pooled_width = (width - pool_size) / stride + 1;  
    std::vector<std::vector<double>> pooled_feature_map(pooled_height, std::vector<double>(pooled_width, 0));  
      
    for (int i = 0; i < height - pool_size + 1; i += stride) {  
        for (int j = 0; j < width - pool_size + 1; j += stride) {  
            double max_val = feature_map[i][j]; // Initialize with the first element in the pooling window  
            for (int k = i; k < i + pool_size; ++k) {  
                for (int l = j; l < j + pool_size; ++l) {  
                    max_val = std::max(max_val, feature_map[k][l]);  
                }  
            }  
            pooled_feature_map[i / stride][j / stride] = max_val;  
        }  
    }  
      
    return pooled_feature_map;  
}  
  
int main() {  
    std::vector<std::vector<double>> feature_map = {  
        {1, 3, 2, 4},  
        {5, 6, 7, 8},  
        {9, 10, 11, 12},  
        {13, 14, 15, 16}  
    };  
      
    // 进行最大池化计算,池化窗口大小为2x2,步长为2  
    std::vector<std::vector<double>> pooled_map = max_pooling(feature_map, 2, 2);  
      
    // 打印池化后的特征图  
    for (const auto& row : pooled_map) {  
        for (double val : row) {  
            std::cout << val << " ";  
        }  
        std::cout << std::endl;  
    }  
      
    return 0;  
}

这两个示例分别展示了如何在Python和C++中手动实现最大池化操作。在实际应用中,为了性能和易用性,我们通常会使用深度学习框架或图像处理库(如OpenCV)中提供的池化函数。

最大池化的优点和缺点可以归纳如下:

优点

  • 保留显著特征:最大池化能够提取每个池化窗口中的最大值,因此对于特征显著性较高的部分能够更好地保留。这一特点使得最大池化在图像处理中特别有用,因为它可以有效地突出图像中的关键特征,如边缘和纹理。

  • 降低维度和计算量:通过减少特征图的尺寸,最大池化能够降低模型的计算复杂度和参数数量,从而提高计算效率。这对于处理大规模图像数据或构建更深层次的网络结构时尤为重要。

  • 位置不变性:最大池化对输入特征图的小平移或略微变形具有一定的鲁棒性。这意味着即使图像中的目标物体发生轻微移动或形变,模型仍然能够识别出它们。

缺点

  1. 信息丢失:最大池化在提取每个池化窗口中的最大值时,会丢弃非最大值的信息。这可能导致一些细节信息的损失,特别是在需要精细分类或识别的任务中,这种信息丢失可能会影响模型的性能。

  2. 过度抽象:在多层网络中连续使用最大池化可能导致信息过度抽象。随着网络层数的增加,最大池化可能会使一些细微的特征被忽略,从而导致模型对某些细节的感知能力下降。

综上所述,最大池化在保留显著特征、降低维度和计算量以及提供位置不变性方面具有优势,但同时也存在信息丢失和过度抽象的风险。在实际应用中,需要根据具体任务的需求来权衡这些优缺点。

3.1.1.6. 前向传播算法示例-全连接层处理

前向传播算法在全连接层(也称为密集层或线性层)中的处理主要涉及到矩阵乘法。以下是在Python和C++中实现全连接层前向传播的示例。

Python 示例

在Python中,我们通常使用NumPy库来进行矩阵运算。以下是一个简单的全连接层前向传播示例:

import numpy as np  
  
def fully_connected_forward(X, W, b):  
    """  
    全连接层的前向传播  
    :param X: 输入数据,形状为 (batch_size, input_dim)  
    :param W: 权重矩阵,形状为 (input_dim, output_dim)  
    :param b: 偏置项,形状为 (output_dim,)  
    :return: 输出数据,形状为 (batch_size, output_dim)  
    """  
    Z = np.dot(X, W) + b  # 矩阵乘法和加法  
    A = 1 / (1 + np.exp(-Z))  # 使用sigmoid激活函数  
    return A  
  
# 示例输入、权重和偏置  
X = np.array([[1, 2, 3], [4, 5, 6]])  # 假设batch_size=2, input_dim=3  
W = np.array([[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]])  # input_dim=3, output_dim=2  
b = np.array([0.1, 0.2])  # output_dim=2  
  
# 执行全连接层的前向传播  
A = fully_connected_forward(X, W, b)  
print(A)

C++ 示例

在C++中,我们可以使用Eigen库来进行矩阵运算。以下是一个简单的全连接层前向传播示例:

#include <iostream>  
#include <Eigen/Dense>  
  
using namespace Eigen;  
using namespace std;  
  
MatrixXd fully_connected_forward(const MatrixXd& X, const MatrixXd& W, const VectorXd& b) {  
    // 矩阵乘法和加法  
    MatrixXd Z = X * W;  
    Z.colwise() += b;  // 将偏置加到每一列上  
      
    // 使用sigmoid激活函数  
    return (1.0 / (1.0 + (-Z).array().exp())).matrix();  
}  
  
int main() {  
    // 示例输入、权重和偏置  
    MatrixXd X(2, 3);  // 假设batch_size=2, input_dim=3  
    X << 1, 2, 3,  
         4, 5, 6;  
           
    MatrixXd W(3, 2);  // input_dim=3, output_dim=2  
    W << 0.1, 0.2,  
         0.3, 0.4,  
         0.5, 0.6;  
           
    VectorXd b(2);  // output_dim=2  
    b << 0.1, 0.2;  
      
    // 执行全连接层的前向传播  
    MatrixXd A = fully_connected_forward(X, W, b);  
      
    // 打印输出  
    cout << "Output:" << endl << A << endl;  
      
    return 0;  
}

请注意,这两个示例都使用了sigmoid激活函数。在实际应用中,你可能会使用其他激活函数,如ReLU、tanh等。你可以根据需要替换激活函数的实现。

另外,为了编译和运行C++示例,你需要安装Eigen库,并在编译时链接到该库。Eigen是一个纯头文件的C++模板库,用于线性代数、矩阵和向量操作,非常适合进行数值计算。

3.1.1.7. 前向传播算法示例-输出层

在输出层,我们通常采用softmax函数估计不同类别的概率。

softmax函数定义

softmax函数,或称归一化指数函数,是逻辑函数的一种推广。它能够将一个含有任意实数的K维向量“压缩”到另一个K维实向量中,使得每一个元素的范围都在(0,1)之间,且所有元素的和为1。这一特性使得softmax函数在表示概率分布时非常有用。

softmax函数公式

给定一个K维输入向量z,softmax函数将其转换为概率分布的公式为:

(softmax(z_i) = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}})

其中,(z_i)是输入向量z的第i个元素,而分母是对所有元素(e^{z_j})的求和,以确保输出向量的所有元素之和为1。

softmax函数的应用

  • 多分类问题:softmax函数广泛应用于多分类问题中,如逻辑回归、线性判别分析以及神经网络等。在这些模型中,softmax函数用于将模型的原始输出转换为对应于每个类别的概率,从而进行类别预测。
  • 图像分类与自然语言处理:在图像分类任务中,softmax函数帮助我们将图像分类到不同的类别,并给出每个类别的概率。此外,在自然语言处理领域,如文本分类和情感分析等任务中,softmax函数也发挥着重要作用。

softmax函数的数学性质

  • 平移不变性:softmax函数对输入的平移不敏感,即输入实数的平移不会改变其输出值。
  • 概率性质:softmax函数的输出满足经典的概率性质,即输出值非负且总和为1。
  • 对称性和可导性:softmax函数保持对称性和可导性,使得输出可以容易地调整,并且其可导性有助于输出更快地收敛于最优值。

softmax函数与交叉熵损失函数

在深度学习中,softmax函数经常与交叉熵损失函数联合使用,用于评估模型预测的概率分布与真实概率分布之间的差异。这种组合在多分类问题中表现出色,有助于提高模型的准确性和泛化能力。

在使用softmax函数作为输出层的激活函数时,我们通常处理的是多分类问题。softmax函数会将输出转换为概率分布,即所有类别的概率之和为1。以下是使用softmax函数在Python和C++中进行前向传播的示例。

Python 示例

import numpy as np  
  
def softmax(x):  
    """  
    计算softmax函数  
    :param x: 输入数组  
    :return: softmax函数的结果  
    """  
    exps = np.exp(x - np.max(x))  # 减去最大值是为了防止数值溢出  
    return exps / np.sum(exps)  
  
def output_layer_forward(Z, activation_func=softmax):  
    """  
    输出层的前向传播  
    :param Z: 输出层的输入,形状通常为 (batch_size, num_classes)  
    :param activation_func: 激活函数,默认为softmax  
    :return: 输出层的输出,即各类别的概率分布  
    """  
    return activation_func(Z)  
  
# 示例输出层的输入  
Z = np.array([[1, 2, 3], [4, 5, 6]])  # 假设batch_size=2, num_classes=3  
  
# 执行输出层的前向传播  
A = output_layer_forward(Z)  
  
print("输出层的概率分布:")  
print(A)

C++ 示例

在C++中,我们可以再次利用Eigen库来计算softmax函数。

#include <iostream>  
#include <Eigen/Dense>  
#include <cmath>  
  
using namespace Eigen;  
using namespace std;  
  
MatrixXd softmax(const MatrixXd& x) {  
    MatrixXd exps = x.array().exp();  
    MatrixXd sums = exps.rowwise().sum();  
    return (exps.array() / sums.array()).matrix();  
}  
  
MatrixXd output_layer_forward(const MatrixXd& Z) {  
    return softmax(Z);  
}  
  
int main() {  
    // 示例输出层的输入  
    MatrixXd Z(2, 3);  // 假设batch_size=2, num_classes=3  
    Z << 1, 2, 3,  
         4, 5, 6;  
           
    // 执行输出层的前向传播  
    MatrixXd A = output_layer_forward(Z);  
      
    // 打印输出层的概率分布  
    cout << "输出层的概率分布:" << endl << A << endl;  
      
    return 0;  
}

请注意,在实际应用中,为了防止softmax函数中的数值溢出,通常会在计算指数之前从输入中减去最大值。在上面的Python示例中,我们已经包含了这一步骤,但在C++示例中为了简洁而省略了。在处理大规模数据时,这一步骤变得尤为重要。

在C++示例中,我们假设所有的输入值都在一个合理的范围内,不会导致数值溢出。如果需要处理可能导致数值溢出的输入,请在计算softmax之前先减去每行(或每列,取决于数据的布局)的最大值。

另外,编译和运行C++代码需要安装Eigen库,并在编译时正确配置。

3.1.2. 整体算法示例

卷积神经网络的Python示例

在Python中,可以使用Keras: Deep Learning for humans等深度学习框架实现卷积神经网络。以下是一个简单的示例,使用CIFAR-10数据集:

from keras.datasets import cifar10  
from keras.models import Sequential  
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense  
  
# 加载数据  
(x_train, y_train), (x_test, y_test) = cifar10.load_data()  
  
# 构建模型  
model = Sequential()  
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))  
model.add(MaxPooling2D(pool_size=(2, 2)))  
model.add(Conv2D(64, (3, 3), activation='relu'))  
model.add(MaxPooling2D(pool_size=(2, 2)))  
model.add(Flatten())  
model.add(Dense(128, activation='relu'))  
model.add(Dense(10, activation='softmax'))  
  
# 编译模型并训练...
# 后面逐步加入这块代码

卷积神经网络的C++示例

在C++中实现卷积神经网络相对复杂,通常需要依赖一些库,如TinyDNN、Caffe | Deep Learning Framework等。以下是一个简化的示例框架,用于说明如何在C++中构建CNN的基本结构:

#include <tiny_dnn/tiny_dnn.h>  
  
using namespace tiny_dnn;  
using namespace tiny_dnn::layers;  
  
int main() {  
    network<sequential> net;  
    net << conv(32, 32, 5, 1, 6) // C1卷积层  
        << relu()               // 激活函数  
        << max_pool(28, 28, 6, 2) // S2池化层  
        << conv(14, 14, 5, 6, 16) // C3卷积层  
        << relu()                // 激活函数  
        << max_pool(10, 10, 16, 2) // S4池化层  
        << fc(16 * 5 * 5, 120)     // F6全连接层  
        << relu()                 // 激活函数  
        << fc(120, 84)             // F7全连接层  
        << relu()                 // 激活函数  
        << fc(84, 10)             // 输出层,假设有10个类别  
        << softmax();             // softmax激活函数  
  
    // 训练网络等后续操作...  
}

请注意,上述C++示例使用了TinyDNN库,这是一个纯C++实现的深度学习库,适用于嵌入式系统和移动平台。在实际应用中,可能需要根据具体任务调整网络结构和参数。

总的来说,卷积神经网络通过卷积层提取图像特征,池化层降低维度和复杂度,全连接层进行分类决策,从而实现对图像等数据的自动学习和识别。

3.2. 循环神经网络(RNN)

能够处理序列数据,如时间序列数据、语音、文本等,在语言模型和机器翻译等任务中表现出色。

游戏AI的创造思路-技术基础-深度学习(2)-CSDN博客文章浏览阅读752次,点赞10次,收藏13次。由于C++实现RNN涉及较多底层细节和TensorFlow C++ API的复杂使用,通常建议先在Python环境中进行模型的开发和调试,然后再考虑将模型导出为可在C++环境中使用的格式(如TensorFlow的SavedModel格式),最后在C++中进行加载和使用。为了解决RNN的这些缺点,研究者们提出了许多改进方案,如LSTM(长短期记忆网络)和GRU(门控循环单元)等变体结构,它们通过引入门控机制和记忆单元来改进RNN的性能,特别是在处理长序列和捕捉长期依赖方面取得了显著进展。https://blog.csdn.net/m0_37694276/article/details/139872578

3.3. 长短期记忆网络(LSTM)

是RNN的一种变体,能够学习长期依赖关系,在文本摘要、语音识别等需要长期记忆的场景中非常有用。

游戏AI的创造思路-技术基础-深度学习(3)-CSDN博客长短期记忆网络(LSTM,Long Short-Term Memory)算法是一种特殊的循环神经网络(RNN),它旨在解决传统RNN在处理长序列数据时遇到的梯度消失和梯度爆炸问题,从而更有效地学习序列中的长期依赖关系。为了最小化训练误差,通常使用梯度下降法,如应用时序性倒传递算法,来依据错误修改每次的权重。此外,LSTM有多种变体,其中一个重要的版本是门控循环单元(GRU)。LSTM适合于处理和预测时间序列中间隔和延迟非常长的重要事件。其表现通常比时间递归神经网络及隐马尔科夫模型(HMM)更好。https://blog.csdn.net/m0_37694276/article/details/139926110

3.4. 生成对抗网络(GAN)

由生成器和判别器两部分组成,在图像生成、数据增强等领域有广泛应用。

3.5. 自编码器(AE)

通过编码器将输入数据压缩成低维表示,然后通过解码器重建数据,常用于降维和特征学习。

3.6. 深度信念网络(DBN)

由多个受限玻尔兹曼机(RBM)堆叠而成,可用于特征学习和预训练。

3.7. Transformer

限于篇幅太长,看着也累写着也累,3.2-3.7的内容将在后续的文章中逐步进行阐述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【内网穿透】FRP 跨平台内网穿透 支持windows linux x86_64 arm64 端口范围映射

AI提供的资料&#xff1a; FRP&#xff08;Fast Reverse Proxy&#xff09;是一个专为内网穿透设计的高性能反向代理程序。以下是一些关于FRP的详细资料&#xff0c;帮助您更好地理解和使用这一工具&#xff1a; 核心特点&#xff1a; 内网穿透&#xff1a;能够将位于内网的…

异常处理的例子

多个except 示例代码如下 try:a input("请输入被除数&#xff1a;")b input("请输入除数&#xff1a;")c float(a)/float(b)print(c)except ZeroDivisionError:print("异常&#xff1a;除数不能为0") except TypeError:print("异常&am…

Vlog视频如何剪辑 Vlog视频剪辑逻辑 视频剪辑制作教程

剪出感觉、剪出情绪&#xff0c;给Vlog视频注入高级氛围感。不用购买昂贵的前期设备&#xff0c;正确地剪辑思维搭配一款好用的视频剪辑软件&#xff0c;你也能剪出令人惊艳的Vlog作品。请收藏本文并反复练习&#xff0c;相信在不久的将来&#xff0c;您的作品必会让人眼前一亮…

【linux基础awk】如何基于强大的awk打印列、计算

打印列 awk {print $1} test.txt#-F参数去指定分隔的字符 awk -F "," {print $1,$2} file 匹配打印列 awk /a/ {print $4 "\t" $3} test.txt筛选数值 仅打印那些含有多于18个字符的行。awk length($0) > 18 test.txt 统计数目 #统计行数 less num…

【Linux】进程信号_1

文章目录 八、进程信号1.信号 未完待续 八、进程信号 1.信号 信号和信号量之间没有任何关系。信号是Linux系统提供的让用户/进程给其他进程发送异步信息的一种方式。 常见信号&#xff1a; 当信号产生时&#xff0c;可选的处理方式有三种&#xff1a;①忽略此信号。②执行该…

机器人控制系列教程之运动规划(2)

简介 在笛卡尔坐标空间中轨迹规划时&#xff0c;首先用位置矢量和旋转矩阵表示所有相应的机器人节点&#xff0c;其次在所有路径段插值计算相对的位置矢量和旋转矩阵&#xff0c;依次得出笛卡尔坐标空间中的轨迹序列通过求解运动学逆问题得到相应关节位置参数。 优点&#xf…

鸿蒙北向开发 ubuntu20.04 gn + ninja环境傻瓜式搭建闭坑指南

ninja跟gn都是比较时髦的东西,由歪果仁维护,如果走下载源码并编译这种流程的话需要走github跟google官网下载,国内的用网环境相信各位傻瓜都知道,github跟google这几年基本是属于连不上的状态,好在你看的鸿蒙项目跟国内的一些软件大厂已经帮你爬过梯子了,ninja工具跟gn工具已经…

PTP时间同步协议简介

注意&#xff0c;上图中 t1 t4 都是主机时间。 t2 t3 都是从机时间。 总延迟为 (t4 - t1) - (t3 - t2) 单边的平均延迟为 ((t4 - t1) - (t3 - t2) ) / 2&#xff0c;公式d1 两边的时钟偏差为 (((t3 t2) / 2)) - ((t4 t1) / 2) 也可以通过下面2个式子 t2 offset delay t1…

CAN报文的发送类型-OnChange、OnWrite、IfActive、Repetition

CAN报文的发送类型分为基本发送类型和混合发送类型两大类 CAN基本发送类型包括Cyclic周期发送、OnChange变化时发送、OnWrite写入时发送和IfActive有效时发送。基本发送类型中的Cyclic称为周期型,而其他3个类型称为事件型(Event)。发送次数是通过定义Repetition重复次数来实…

实用软件下载:ABBYY Finereader 15最新安装包及详细安装教程

数据表明FineReader PDF提供实用、简易的工具&#xff0c;将纸质文档和PDF结合起来&#xff0c;提高了数字工作场所的效率。我们都知道 即时背景识别:使不可搜索的PDF能够在工作中立即使用。值得一提的是文档转换更精准&#xff1a;OCR技术&#xff0c;它提高了PDF转换、布局保…

深入解析Elasticsearch 8.4.1:Mapping与字段类型实战指南

标题Elasticsearch8.4.1常见字段类型介绍 Mapping概述 在Elasticsearch中&#xff0c;Mapping定义了索引中每个字段的类型、属性以及设置。Mapping的作用是告诉Elasticsearch如何索引文档中的字段&#xff0c;包括如何分析字段值以及如何存储它们。 常见字段类型 字符串类型…

el-progress进度条,format效果实现

需要实现如下效果图: 实现的需求是,取数组对象里面,amount最大的值作为100%,其余按照这个标准进行计算得到显示的进度条百分比 <template><div class="app-container"> <div class="chart-container"><el-row :gutter="1…

睡眠剥夺对记忆巩固的神经生物学影响

近期&#xff0c;《自然》杂志刊载的研究揭示了睡眠不足对记忆相关神经信号的不利影响&#xff0c;强调了即使在后续恢复充分睡眠的情况下&#xff0c;这种损害亦难以完全逆转。 神经元作为大脑的基本功能单位&#xff0c;其活动并非孤立进行&#xff0c;而是通过复杂的网络连接…

Day45

Day45 jQuery动画 显示和隐藏 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title><script src"js/jquery-1.8.2.js" type"text/javascript" charset"utf-8"></script&…

Webpack: 借助 Babel+TS+ESLint 构建现代 JS 工程环境

概述 Webpack 场景下处理 JavaScript 的三种常用工具&#xff1a;Babel、TypeScript、ESLint 的历史背景、功能以及接入 Webpack 的步骤借助这些工具&#xff0c;我们能构建出更健壮、优雅的 JavaScript 应用 使用 Babel ECMAScript 6.0(简称 ES6) 版本补充了大量提升 JavaSc…

【Linux】进程 | 控制块pcb | task_struct | 创建子进程fork

目录 Ⅰ. 进程的概念&#xff08;Process&#xff09; 1. 什么是进程&#xff1f; 2. 多进程管理 3. 进程控制块&#xff08;PCB&#xff09; task_struct 的结构 Ⅱ. 进程查看与管理 1. 使用指令查看进程 2. /proc 查看进程信息 3. 获取进程 ID 4. 创建子进程 原因…

Vue2-表单与v-model

1.Vue表单使用 表单输入绑定&#xff1a;表单输入绑定 — Vue.js #v-model双向数据绑定new Vue({template: <div>/* 用户修改 , vue-data数据同步修改(内存) */<input v-model"message" placeholder"edit..."><p>message: {{message}}&…

2024年虚拟现实、图像和信号处理国际学术会议(ICVISP 2024,8月2日-4)

2024年虚拟现实、图像和信号处理国际学术会议&#xff08;ICVISP 2024&#xff09;将于2024年8月2-4日在中国厦门召开。ICVISP 2024将围绕“虚拟现实、图像和信号处理”的最新研究领域&#xff0c; 为来自国内外高等院校、科学研究所、企事业单位的专家、教授、学者、工程师等提…

Python 参数类型

一 理解Python中的Parameters & Arguments Parameters&#xff1a;形参 Arguments&#xff1a;实参 二 Python的实参&#xff08;Arguments&#xff09;类型 实参类型总结 位置参数&#xff08;Positional Arguments&#xff09; &#xff1a;函数调用时通过入参的顺序来…

Younger 数据集:人工智能生成神经网络

设计和优化神经网络架构通常需要广泛的专业知识&#xff0c;从手工设计开始&#xff0c;然后进行手动或自动化的精细化改进。这种依赖性成为快速创新的重要障碍。认识到从头开始自动生成神经网络架构的复杂性&#xff0c;本文引入了Younger&#xff0c;这是一个开创性的数据集&…