政安晨:【Keras机器学习示例演绎】(二十八)—— 使用 卷积神经网络与循环神经网络 架构进行视频分类

目录

数据收集

设置

定义超参数

数据准备

序列模型

推论


政安晨的个人主页政安晨

欢迎 👍点赞✍评论⭐收藏

收录专栏: TensorFlow与Keras机器学习实战

希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正!

文本目标:在 UCF101 数据集上使用迁移学习和递归模型训练视频分类器。

该示例演示了视频分类,这是在推荐、安全等领域应用的一个重要用例。

我们将使用 UCF101 数据集来构建视频分类器。

该数据集包含按不同动作分类的视频,如板球投篮、拳击、骑自行车等。

该数据集通常用于构建动作识别器,这是视频分类的一种应用。

视频由有序的帧序列组成。

每个帧都包含空间信息,而这些帧的序列则包含时间信息。

为了对这两方面进行建模,我们使用了一种混合架构,其中包括卷积层(用于空间处理)和递归层(用于时间处理)。

具体来说,我们将使用由 GRU 层组成的卷积神经网络 (CNN) 和递归神经网络 (RNN)。这种混合架构俗称 CNN-RNN。

数据收集


为了缩短本示例的运行时间,我们将使用 UCF101 原始数据集的子采样版本。您可以参考本笔记本了解如何进行子采样。

!!wget -q https://github.com/sayakpaul/Action-Recognition-in-TensorFlow/releases/download/v1.0.0/ucf101_top5.tar.gz
!tar xf ucf101_top5.tar.gz

设置

import os

import keras
from imutils import paths

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import imageio
import cv2
from IPython.display import Image

定义超参数

IMG_SIZE = 224
BATCH_SIZE = 64
EPOCHS = 10

MAX_SEQ_LENGTH = 20
NUM_FEATURES = 2048

数据准备

train_df = pd.read_csv("train.csv")
test_df = pd.read_csv("test.csv")

print(f"Total videos for training: {len(train_df)}")
print(f"Total videos for testing: {len(test_df)}")

train_df.sample(10)
Total videos for training: 594
Total videos for testing: 224
video_nametag
492v_TennisSwing_g10_c03.aviTennisSwing
536v_TennisSwing_g16_c05.aviTennisSwing
413v_ShavingBeard_g16_c05.aviShavingBeard
268v_Punch_g12_c04.aviPunch
288v_Punch_g15_c03.aviPunch
30v_CricketShot_g12_c03.aviCricketShot
449v_ShavingBeard_g21_c07.aviShavingBeard
524v_TennisSwing_g14_c07.aviTennisSwing
145v_PlayingCello_g12_c01.aviPlayingCello
566v_TennisSwing_g21_c03.aviTennisSwing

训练视频分类器的众多挑战之一是找出将视频输入网络的方法。本博文将讨论五种此类方法。由于视频是有序的帧序列,我们可以直接提取帧并将其放入三维张量中。但不同视频的帧数可能不同,这就导致我们无法将它们堆叠成批(除非使用填充)。作为替代方法,我们可以以固定的间隔保存视频帧,直到达到最大帧数为止。在本例中,我们将这样做:

1.捕捉视频帧。
2.从视频中提取帧数,直至达到最大帧数。
3.如果视频帧数小于最大帧数,我们将在视频中填充 0。

请注意,此工作流程与涉及文本序列的问题相同。众所周知,UCF101 数据集的视频不包含跨帧对象和动作的极端变化。正因为如此,在学习任务中只考虑几帧画面可能没有问题。但这种方法可能无法很好地推广到其他视频分类问题中。我们将使用 OpenCV 的 VideoCapture() 方法从视频中读取帧。

# The following two methods are taken from this tutorial:


def crop_center_square(frame):
    y, x = frame.shape[0:2]
    min_dim = min(y, x)
    start_x = (x // 2) - (min_dim // 2)
    start_y = (y // 2) - (min_dim // 2)
    return frame[start_y : start_y + min_dim, start_x : start_x + min_dim]


def load_video(path, max_frames=0, resize=(IMG_SIZE, IMG_SIZE)):
    cap = cv2.VideoCapture(path)
    frames = []
    try:
        while True:
            ret, frame = cap.read()
            if not ret:
                break
            frame = crop_center_square(frame)
            frame = cv2.resize(frame, resize)
            frame = frame[:, :, [2, 1, 0]]
            frames.append(frame)

            if len(frames) == max_frames:
                break
    finally:
        cap.release()
    return np.array(frames)

我们可以使用预训练网络从提取的帧中提取有意义的特征。Keras 应用模块提供了许多在 ImageNet-1k 数据集上预先训练过的先进模型。为此,我们将使用 InceptionV3 模型。

def build_feature_extractor():
    feature_extractor = keras.applications.InceptionV3(
        weights="imagenet",
        include_top=False,
        pooling="avg",
        input_shape=(IMG_SIZE, IMG_SIZE, 3),
    )
    preprocess_input = keras.applications.inception_v3.preprocess_input

    inputs = keras.Input((IMG_SIZE, IMG_SIZE, 3))
    preprocessed = preprocess_input(inputs)

    outputs = feature_extractor(preprocessed)
    return keras.Model(inputs, outputs, name="feature_extractor")


feature_extractor = build_feature_extractor()

视频的标签是字符串。神经网络无法理解字符串值,因此在将其输入模型之前,必须将其转换为某种数值形式。在这里,我们将使用 StringLookup 层将类标签编码为整数。

label_processor = keras.layers.StringLookup(
    num_oov_indices=0, vocabulary=np.unique(train_df["tag"])
)
print(label_processor.get_vocabulary())
['CricketShot', 'PlayingCello', 'Punch', 'ShavingBeard', 'TennisSwing']

最后,我们就可以将所有部件组合在一起,创建我们的数据处理实用程序。

def prepare_all_videos(df, root_dir):
    num_samples = len(df)
    video_paths = df["video_name"].values.tolist()
    labels = df["tag"].values
    labels = keras.ops.convert_to_numpy(label_processor(labels[..., None]))

    # `frame_masks` and `frame_features` are what we will feed to our sequence model.
    # `frame_masks` will contain a bunch of booleans denoting if a timestep is
    # masked with padding or not.
    frame_masks = np.zeros(shape=(num_samples, MAX_SEQ_LENGTH), dtype="bool")
    frame_features = np.zeros(
        shape=(num_samples, MAX_SEQ_LENGTH, NUM_FEATURES), dtype="float32"
    )

    # For each video.
    for idx, path in enumerate(video_paths):
        # Gather all its frames and add a batch dimension.
        frames = load_video(os.path.join(root_dir, path))
        frames = frames[None, ...]

        # Initialize placeholders to store the masks and features of the current video.
        temp_frame_mask = np.zeros(
            shape=(
                1,
                MAX_SEQ_LENGTH,
            ),
            dtype="bool",
        )
        temp_frame_features = np.zeros(
            shape=(1, MAX_SEQ_LENGTH, NUM_FEATURES), dtype="float32"
        )

        # Extract features from the frames of the current video.
        for i, batch in enumerate(frames):
            video_length = batch.shape[0]
            length = min(MAX_SEQ_LENGTH, video_length)
            for j in range(length):
                temp_frame_features[i, j, :] = feature_extractor.predict(
                    batch[None, j, :], verbose=0,
                )
            temp_frame_mask[i, :length] = 1  # 1 = not masked, 0 = masked

        frame_features[idx,] = temp_frame_features.squeeze()
        frame_masks[idx,] = temp_frame_mask.squeeze()

    return (frame_features, frame_masks), labels


train_data, train_labels = prepare_all_videos(train_df, "train")
test_data, test_labels = prepare_all_videos(test_df, "test")

print(f"Frame features in train set: {train_data[0].shape}")
print(f"Frame masks in train set: {train_data[1].shape}")
Frame features in train set: (594, 20, 2048)
Frame masks in train set: (594, 20)

上述代码块的执行时间约为 20 分钟,具体取决于执行的机器。

序列模型


现在,我们可以将这些数据输入由 GRU 等递归层组成的序列模型。

# Utility for our sequence model.
def get_sequence_model():
    class_vocab = label_processor.get_vocabulary()

    frame_features_input = keras.Input((MAX_SEQ_LENGTH, NUM_FEATURES))
    mask_input = keras.Input((MAX_SEQ_LENGTH,), dtype="bool")

    # Refer to the following tutorial to understand the significance of using `mask`:
    # https://keras.io/api/layers/recurrent_layers/gru/
    x = keras.layers.GRU(16, return_sequences=True)(
        frame_features_input, mask=mask_input
    )
    x = keras.layers.GRU(8)(x)
    x = keras.layers.Dropout(0.4)(x)
    x = keras.layers.Dense(8, activation="relu")(x)
    output = keras.layers.Dense(len(class_vocab), activation="softmax")(x)

    rnn_model = keras.Model([frame_features_input, mask_input], output)

    rnn_model.compile(
        loss="sparse_categorical_crossentropy", optimizer="adam", metrics=["accuracy"]
    )
    return rnn_model


# Utility for running experiments.
def run_experiment():
    filepath = "/tmp/video_classifier/ckpt.weights.h5"
    checkpoint = keras.callbacks.ModelCheckpoint(
        filepath, save_weights_only=True, save_best_only=True, verbose=1
    )

    seq_model = get_sequence_model()
    history = seq_model.fit(
        [train_data[0], train_data[1]],
        train_labels,
        validation_split=0.3,
        epochs=EPOCHS,
        callbacks=[checkpoint],
    )

    seq_model.load_weights(filepath)
    _, accuracy = seq_model.evaluate([test_data[0], test_data[1]], test_labels)
    print(f"Test accuracy: {round(accuracy * 100, 2)}%")

    return history, seq_model


_, sequence_model = run_experiment()

演绎展示:

Epoch 1/10
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 9ms/step - accuracy: 0.3058 - loss: 1.5597 
Epoch 1: val_loss improved from inf to 1.78077, saving model to /tmp/video_classifier/ckpt.weights.h5
 13/13 ━━━━━━━━━━━━━━━━━━━━ 2s 36ms/step - accuracy: 0.3127 - loss: 1.5531 - val_accuracy: 0.1397 - val_loss: 1.7808
Epoch 2/10
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 9ms/step - accuracy: 0.5216 - loss: 1.2704
Epoch 2: val_loss improved from 1.78077 to 1.78026, saving model to /tmp/video_classifier/ckpt.weights.h5
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 13ms/step - accuracy: 0.5226 - loss: 1.2684 - val_accuracy: 0.1788 - val_loss: 1.7803
Epoch 3/10
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 9ms/step - accuracy: 0.6189 - loss: 1.1656
Epoch 3: val_loss did not improve from 1.78026
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 12ms/step - accuracy: 0.6174 - loss: 1.1651 - val_accuracy: 0.2849 - val_loss: 1.8322
Epoch 4/10
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 9ms/step - accuracy: 0.6518 - loss: 1.0645
Epoch 4: val_loss did not improve from 1.78026
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 13ms/step - accuracy: 0.6515 - loss: 1.0647 - val_accuracy: 0.2793 - val_loss: 2.0419
Epoch 5/10
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 9ms/step - accuracy: 0.6833 - loss: 0.9976
Epoch 5: val_loss did not improve from 1.78026
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 12ms/step - accuracy: 0.6843 - loss: 0.9965 - val_accuracy: 0.3073 - val_loss: 1.9077
Epoch 6/10
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 9ms/step - accuracy: 0.7229 - loss: 0.9312
Epoch 6: val_loss did not improve from 1.78026
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 12ms/step - accuracy: 0.7241 - loss: 0.9305 - val_accuracy: 0.3017 - val_loss: 2.1513
Epoch 7/10
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 9ms/step - accuracy: 0.8023 - loss: 0.9132
Epoch 7: val_loss did not improve from 1.78026
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 12ms/step - accuracy: 0.8035 - loss: 0.9093 - val_accuracy: 0.3184 - val_loss: 2.1705
Epoch 8/10
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 9ms/step - accuracy: 0.8127 - loss: 0.8380
Epoch 8: val_loss did not improve from 1.78026
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 12ms/step - accuracy: 0.8128 - loss: 0.8356 - val_accuracy: 0.3296 - val_loss: 2.2043
Epoch 9/10
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 9ms/step - accuracy: 0.8494 - loss: 0.7641
Epoch 9: val_loss did not improve from 1.78026
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 12ms/step - accuracy: 0.8494 - loss: 0.7622 - val_accuracy: 0.3017 - val_loss: 2.3734
Epoch 10/10
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 9ms/step - accuracy: 0.8634 - loss: 0.6883
Epoch 10: val_loss did not improve from 1.78026
 13/13 ━━━━━━━━━━━━━━━━━━━━ 0s 12ms/step - accuracy: 0.8649 - loss: 0.6882 - val_accuracy: 0.3240 - val_loss: 2.4410
 7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - accuracy: 0.7816 - loss: 1.0624 
Test accuracy: 56.7%

注:为了缩短本示例的运行时间,我们只使用了几个训练示例。

与拥有 99,909 个可训练参数的序列模型相比,训练示例的数量较少。我们鼓励您使用上述笔记本从 UCF101 数据集中采样更多数据,并训练相同的模型。

推论

def prepare_single_video(frames):
    frames = frames[None, ...]
    frame_mask = np.zeros(
        shape=(
            1,
            MAX_SEQ_LENGTH,
        ),
        dtype="bool",
    )
    frame_features = np.zeros(shape=(1, MAX_SEQ_LENGTH, NUM_FEATURES), dtype="float32")

    for i, batch in enumerate(frames):
        video_length = batch.shape[0]
        length = min(MAX_SEQ_LENGTH, video_length)
        for j in range(length):
            frame_features[i, j, :] = feature_extractor.predict(batch[None, j, :])
        frame_mask[i, :length] = 1  # 1 = not masked, 0 = masked

    return frame_features, frame_mask


def sequence_prediction(path):
    class_vocab = label_processor.get_vocabulary()

    frames = load_video(os.path.join("test", path))
    frame_features, frame_mask = prepare_single_video(frames)
    probabilities = sequence_model.predict([frame_features, frame_mask])[0]

    for i in np.argsort(probabilities)[::-1]:
        print(f"  {class_vocab[i]}: {probabilities[i] * 100:5.2f}%")
    return frames


# This utility is for visualization.
# Referenced from:

def to_gif(images):
    converted_images = images.astype(np.uint8)
    imageio.mimsave("animation.gif", converted_images, duration=100)
    return Image("animation.gif")


test_video = np.random.choice(test_df["video_name"].values.tolist())
print(f"Test video path: {test_video}")
test_frames = sequence_prediction(test_video)
to_gif(test_frames[:MAX_SEQ_LENGTH])

演绎展示:

Test video path: v_TennisSwing_g03_c01.avi
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step
 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 166ms/step
  CricketShot: 46.99%
  ShavingBeard: 18.83%
  TennisSwing: 14.65%
  Punch: 12.41%
  PlayingCello:  7.12%

<IPython.core.display.Image object>

下一步


—— 在本例中,我们利用迁移学习从视频帧中提取有意义的特征。您还可以对预训练网络进行微调,以了解其对最终结果的影响。
—— 如果要权衡速度和准确性,可以尝试 keras.applications 中的其他模型。
—— 尝试 MAX_SEQ_LENGTH 的不同组合,观察其对性能的影响。
—— 对更多的类进行训练,看看能否获得良好的性能。
—— 按照本教程,尝试使用 DeepMind 预先训练好的动作识别模型。
—— 滚动平均法是一种有用的视频分类技术,它可以与标准图像分类模型相结合,对视频进行推断。本教程将帮助您了解如何将滚动平均法与图像分类器结合使用。
—— 当视频帧与帧之间存在变化时,并非所有帧都对确定视频类别同等重要。在这种情况下,在—— 序列模型中加入自关注层可能会产生更好的结果。
通过本文的学习,你可以实现基于变换器的视频处理模型。


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

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

相关文章

Android Handler用法

Android Handler用法 为什么要设计Handler机制&#xff1f;Handler的用法1、创建Handler2、Handler通信2.1 sendMessage 方式2.2 post 方式 Handler常用方法1、延时执行2、周期执行 HandlerThread用法主线程-创建Handler子线程-创建Handler FAQMessage是如何创建主线程中Looper…

微服务保护和分布式事务(Sentinel、Seata)笔记

一、雪崩问题的解决的服务保护技术了解 二、Sentinel 2.1Sentinel入门 1.Sentinel的安装 &#xff08;1&#xff09;下载Sentinel的tar安装包先 &#xff08;2&#xff09;将jar包放在任意非中文、不包含特殊字符的目录下&#xff0c;重命名为 sentinel-dashboard.jar &…

Docker容器---Harbor私有仓库部署与管理

一、搭建本地私有仓库 1、下载registry镜像 [rootlocalhost ~]#docker pull registry Using default tag: latest latest: Pulling from library/registry 79e9f2f55bf5: Pull complete 0d96da54f60b: Pull complete 5b27040df4a2: Pull complete e2ead8259a04: Pull comp…

vulnhub靶场之FunBox-1

一.环境搭建 1.靶场描述 Boot2Root ! This is a reallife szenario, but easy going. You have to enumerate and understand the szenario to get the root-flag in round about 20min. This VM is created/tested with Virtualbox. Maybe it works with vmware. If you n…

NASA数据集——NASA 标准二级(L2)暗目标(DT)气溶胶产品每 6 分钟在全球范围内对陆地和海洋上空的气溶胶光学厚度(AOT)产品

VIIRS/NOAA20 Dark Target Aerosol 6-Min L2 Swath 6 km 简介 NOAA-20&#xff08;前身为联合极地卫星系统-1&#xff08;JPSS-1&#xff09;&#xff09;--可见红外成像辐射计套件&#xff08;VIIRS&#xff09;NASA 标准二级&#xff08;L2&#xff09;暗目标&#xff08;D…

集合的基本操作

集合&#xff1a; 在java当中&#xff0c;含有着一些不同的存储数据的相关集合。分为单列集合&#xff08;Collection&#xff09;和双列集合(Map)。 Collection 首先学习Collection来进行展示&#xff1a; 以框框为例子&#xff0c;蓝色的代表的是接口&#xff0c;而红色的…

【Linux极简教程】常见实用命令不断更新中......

【Linux极简教程】常见实用命令不断更新中...... 常见问题1.Waiting for cache lock: Could not get lock /var/lib/dpkg/lock. It is held by process xxxx(dpkg) 常见问题 1.Waiting for cache lock: Could not get lock /var/lib/dpkg/lock. It is held by process xxxx(dp…

机器学习:基于Sklearn、XGBoost,使用逻辑回归、支持向量机和XGBClassifier预测股票价格

前言 系列专栏&#xff1a;机器学习&#xff1a;高级应用与实践【项目实战100】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目&#xff0c;每个项目都处理一组不同的问题&#xff0c;包括监督和无监督学习、分类、回归和聚类&#xff0c;而且涉及创建深度学…

C语言——队列的实现

队列按照先进先出&#xff08;FIFO&#xff0c;First In First Out&#xff09;的原则管理数据。这意味着最先进入队列的元素会被最先移出&#xff0c;类似于排队等候服务的情况。队列通常有两个主要操作&#xff1a;入队&#xff08;enqueue&#xff09;&#xff0c;将元素添加…

DSP实时分析平台设计方案:924-6U CPCI振动数据DSP实时分析平台

6U CPCI振动数据DSP实时分析平台 一、产品概述 基于CPCI结构完成40路AD输入&#xff0c;30路DA输出的信号处理平台&#xff0c;处理平台采用双DSPFPGA的结构&#xff0c;DSP采用TI公司新一代DSP TMS320C6678&#xff0c;FPGA采用Xilinx V5 5VLX110T-1FF1136芯片&#xff…

《QT实用小工具·五十》动态增删数据与平滑缩放移动的折线图

1、概述 源码放在文章末尾 该项目实现了带动画、带交互的折线图&#xff0c;包含如下特点&#xff1a; 动态增删数值 自适应显示坐标轴数值 鼠标悬浮显示十字对准线 鼠标靠近点自动贴附 支持直线与平滑曲线效果 自定义点的显示类型与大小 自适应点的数值显示位置 根据指定锚点…

java并发编程-AQS介绍及源码详解

介绍 AQS 的全称为 AbstractQueuedSynchronizer &#xff0c;就是抽象队列同步器。 从源码上可以看到AQS 就是一个抽象类&#xff0c;它继承了AbstractOwnableSynchronizer&#xff0c;实现了java.io.Serializable接口。 public abstract class AbstractQueuedSynchronizere…

redis缓存详情

redis安装包及图形化软件: 百度链接&#xff1a;https://pan.baidu.com/s/1wljo7JzgrSQyqldv9d5HZA?pwdht1m 提取码&#xff1a;ht1m 目录 1.redis的下载及安装 1.1redis的启动与停止 1.2Redis服务启动与停止 2.redis数据类型及常用指令 2.1redis数据类型 2.2redis常用…

读天才与算法:人脑与AI的数学思维笔记15_声响的数学之旅

1. 音乐 1.1. 巴赫的作品以严格的对位著称&#xff0c;他十分中意对称的结构 1.2. 巴托克的作品很多都以黄金比例为结构基础&#xff0c;他非常喜欢并善于使用斐波纳契数列 1.3. 有时&#xff0c;作曲家是本能地或者不自知地被数学的模式和结构所吸引&#xff0c;而他们并没…

Golang | Leetcode Golang题解之第61题旋转链表

题目&#xff1a; 题解&#xff1a; func rotateRight(head *ListNode, k int) *ListNode {if k 0 || head nil || head.Next nil {return head}n : 1iter : headfor iter.Next ! nil {iter iter.Nextn}add : n - k%nif add n {return head}iter.Next headfor add > …

【项目构建】04:动态库与静态库制作

OVERVIEW 1.编译动态链接库&#xff08;1&#xff09;编译动态库&#xff08;2&#xff09;链接动态库&#xff08;3&#xff09;运行时使用动态库 2.编译静态链接库&#xff08;1&#xff09;编译静态库&#xff08;2&#xff09;链接静态库&#xff08;3&#xff09;运行时使…

matlab学习007-已知离散时间系统的系统函数并使用matlab绘制该系统的零极点图;判断系统的稳定性;幅频和相频特性曲线

目录 题目 离散时间系统的系统函数&#xff1a;H(z)(3*z^3-5*z^210z)/(z^3-3*z^27*z-5) 1&#xff0c;绘制该系统的零极点图 1&#xff09;零极点图 2&#xff09;代码 2&#xff0c;判断系统的稳定性 1&#xff09;判断结果 2&#xff09;代码 3&#xff0c;试用MATL…

C++的未来之路:探索与突破

在计算机科学的浩瀚星空中&#xff0c;C无疑是一颗璀璨的明星。自诞生以来&#xff0c;它以其强大的性能和灵活的特性&#xff0c;赢得了无数开发者的青睐。然而&#xff0c;随着技术的不断进步和应用的日益复杂&#xff0c;C也面临着前所未有的挑战和机遇。本文将探讨C的未来之…

腾锐D2000-8 MXM VPX,全国产,可广泛应用于边缘计算网关、入侵检测、VPN、网络监控等等应用领域

腾锐D2000-8 MXM VPX 1. 概述 XMVPX-108 是一款基于飞腾 D2000/8 处理器的低功耗逻辑运算和图形处理 VPX 刀片&#xff0c; 板贴 32GB DDR4 内存&#xff0c;搭载飞腾 X100 套片&#xff0c;满足通用 IO 接口功能。GPU 采用 MXM 小型插卡形式&#xff0c; 搭配 8GB 显卡。提供…

【16-降维技术:PCA与LDA在Scikit-learn中的应用】

文章目录 前言主成分分析(PCA)原理简介Scikit-learn中的PCA实现应用示例线性判别分析(LDA)原理简介Scikit-learn中的LDA实现应用示例总结前言 降维是机器学习中一种常见的数据预处理方法,旨在减少数据集的特征数量,同时尽量保留原始数据集的重要信息。这不仅有助于减少计…
最新文章