政安晨:【Keras机器学习实践要点】(六)—— 使用内置方法进行训练和评估

news2024/11/18 5:34:45

政安晨的个人主页政安晨

欢迎 👍点赞✍评论⭐收藏

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

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

本文涵盖使用内置 API 进行训练和验证(如 Model.fit()、Model.evaluate() 和 Model.predict())时的训练、评估和预测(推理)模型。


一般来说,无论您是使用内置循环还是编写自己的循环,模型训练和评估在每种 Keras 模型中的工作方式都是严格相同的包括顺序模型、使用功能 API 构建的模型以及通过模型子类化从头编写的模型。

本文作者政安晨使用Kaggle的线上环境进行实战演绎。

我线上选择的是CPU版本:

当我需要做训练的时候,点击右上角可以切换为GPU版本


导入

# We import torch & TF so as to use torch Dataloaders & tf.data.Datasets.
import torch
import tensorflow as tf

import os
import numpy as np
import keras
from keras import layers
from keras import ops

应用程序接口概述:第一个端到端示例

向模型的内置训练循环传递数据时,应使用:

* NumPy 数组(如果您的数据较小且适合在内存中使用)
* keras.utils.PyDataset 的子类
* tf.data.Dataset 对象
* PyTorch 数据加载器实例

在接下来的几段中,我们将使用 MNIST 数据集作为 NumPy 数组,以演示如何使用优化器、损失和度量。之后,我们将仔细研究其他选项


让我们考虑下面的模型(在这里,我们使用函数式 API 构建模型,但它也可以是顺序模型或子类模型

inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, activation="softmax", name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)

以下是典型的端到端工作流程,包括

* 训练
* 在原始训练数据生成的保留集上进行验证
* 在测试数据上进行评估


在这个例子中,我们将使用 MNIST 数据。

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

# Preprocess the data (these are NumPy arrays)
x_train = x_train.reshape(60000, 784).astype("float32") / 255
x_test = x_test.reshape(10000, 784).astype("float32") / 255

y_train = y_train.astype("float32")
y_test = y_test.astype("float32")

# Reserve 10,000 samples for validation
x_val = x_train[-10000:]
y_val = y_train[-10000:]
x_train = x_train[:-10000]
y_train = y_train[:-10000]

演绎如下

我们指定训练配置(优化器、损失、指标)

model.compile(
    optimizer=keras.optimizers.RMSprop(),  # Optimizer
    # Loss function to minimize
    loss=keras.losses.SparseCategoricalCrossentropy(),
    # List of metrics to monitor
    metrics=[keras.metrics.SparseCategoricalAccuracy()],
)

我们调用 fit(),它将把数据切成大小为 batch_size 的 "批次",并在给定的时间内反复迭代整个数据集,从而训练模型

print("Fit model on training data")
history = model.fit(
    x_train,
    y_train,
    batch_size=64,
    epochs=2,
    # We pass some validation for
    # monitoring validation loss and metrics
    # at the end of each epoch
    validation_data=(x_val, y_val),
)

咱们将要训练时,按照刚才提到的,将Kaggle的环境从CPU改为GPU

接下来继续我们的训练

返回的历史对象记录了训练过程中的损失值和度量值:

我们通过 evaluate() 在测试数据上对模型进行评估

# Evaluate the model on the test data using `evaluate`
print("Evaluate on test data")
results = model.evaluate(x_test, y_test, batch_size=128)
print("test loss, test acc:", results)

# Generate predictions (probabilities -- the output of the last layer)
# on new data using `predict`
print("Generate predictions for 3 samples")
predictions = model.predict(x_test[:3])
print("predictions shape:", predictions.shape)

演绎如下

现在,让我们来详细回顾一下这个工作流程的各个部分

编译()方法:指定损失、度量和优化器

要使用 fit() 训练一个模型,需要指定一个损失函数、一个优化器,还可以选择一些监控指标

您可以将这些参数作为编译()方法的参数传递给模型

model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[keras.metrics.SparseCategoricalAccuracy()],
)

度量参数应该是一个列表--你的模型可以有任意数量的度量参数

如果模型有多个输出,可以为每个输出指定不同的损耗和度量,还可以调节每个输出对模型总损耗的贡献。

请注意,如果您对默认设置感到满意,在许多情况下,可以通过字符串标识符来指定优化器、损耗和度量作为快捷方式

model.compile(
    optimizer="rmsprop",
    loss="sparse_categorical_crossentropy",
    metrics=["sparse_categorical_accuracy"],
)

为便于以后重用,让我们把模型定义和编译步骤放在函数中;我们将在本文的不同示例中多次调用它们。

def get_uncompiled_model():
    inputs = keras.Input(shape=(784,), name="digits")
    x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
    x = layers.Dense(64, activation="relu", name="dense_2")(x)
    outputs = layers.Dense(10, activation="softmax", name="predictions")(x)
    model = keras.Model(inputs=inputs, outputs=outputs)
    return model


def get_compiled_model():
    model = get_uncompiled_model()
    model.compile(
        optimizer="rmsprop",
        loss="sparse_categorical_crossentropy",
        metrics=["sparse_categorical_accuracy"],
    )
    return model

Keras提供许多内置优化器、损耗和指标

一般来说,您不必从头开始创建自己的损失、度量或优化器,因为您需要的东西很可能已经是 Keras API 的一部分

优化器:

  • SGD() (with or without momentum)
  • RMSprop()
  • Adam()
  • etc.


损失:

  • MeanSquaredError()
  • KLDivergence()
  • CosineSimilarity()
  • etc.


度量:

  • AUC()
  • Precision()
  • Recall()
  • etc.

定制损失

如果需要创建自定义损失,Keras 提供了三种方法

第一种方法是创建一个接受输入 y_true 和 y_pred 的函数。下面的示例显示了一个计算真实数据与预测之间均方误差的损失函数

def custom_mean_squared_error(y_true, y_pred):
    return ops.mean(ops.square(y_true - y_pred), axis=-1)


model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=custom_mean_squared_error)

# We need to one-hot encode the labels to use MSE
y_train_one_hot = ops.one_hot(y_train, num_classes=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)

结果如下

如果需要一个除了 y_true 和 y_pred 之外还能接收其他参数的损失函数,可以子类化 keras.losses.Loss 类并实现以下两个方法:
 

__init__(self):在调用损失函数时接受要传递的参数
call(self,y_true,y_pred):使用目标(y_true)和模型预测(y_pred)计算模型的损失

比方说,您想使用均方误差,但要加上一个项,以抑制预测值偏离 0.5(我们假设分类目标是单击编码的,取值在 0 和 1 之间)。

这将激励模型不要过于自信,从而有助于减少过度拟合(不试试怎么知道行不行!)。

具体做法如下:

class CustomMSE(keras.losses.Loss):
    def __init__(self, regularization_factor=0.1, name="custom_mse"):
        super().__init__(name=name)
        self.regularization_factor = regularization_factor

    def call(self, y_true, y_pred):
        mse = ops.mean(ops.square(y_true - y_pred), axis=-1)
        reg = ops.mean(ops.square(0.5 - y_pred), axis=-1)
        return mse + reg * self.regularization_factor


model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=CustomMSE())

y_train_one_hot = ops.one_hot(y_train, num_classes=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)

结果如下:

自定义指标

如果您需要的度量指标不是 API 的一部分,您可以通过子类化 keras.metrics.Metric 类轻松创建自定义度量指标。您需要实现 4 个方法:

__init__(self),您将在其中为度量创建状态变量。
update_state(self,y_true,y_pred,sample_weight=None),使用目标 y_true 和模型预测 y_pred 更新状态变量。
result(self),使用状态变量计算最终结果。
reset_state(self),用于重新初始化度量器的状态。


状态更新和结果计算是分开的(分别在 update_state() 和 result() 中),因为在某些情况下,结果计算可能非常昂贵,而且只能定期进行。

下面是一个简单的示例,展示了如何实现 CategoricalTruePositives 指标,该指标用于计算有多少样本被正确分类为属于给定类别:

class CategoricalTruePositives(keras.metrics.Metric):
    def __init__(self, name="categorical_true_positives", **kwargs):
        super().__init__(name=name, **kwargs)
        self.true_positives = self.add_variable(
            shape=(), name="ctp", initializer="zeros"
        )

    def update_state(self, y_true, y_pred, sample_weight=None):
        y_pred = ops.reshape(ops.argmax(y_pred, axis=1), (-1, 1))
        values = ops.cast(y_true, "int32") == ops.cast(y_pred, "int32")
        values = ops.cast(values, "float32")
        if sample_weight is not None:
            sample_weight = ops.cast(sample_weight, "float32")
            values = ops.multiply(values, sample_weight)
        self.true_positives.assign_add(ops.sum(values))

    def result(self):
        return self.true_positives.value

    def reset_state(self):
        # The state of the metric will be reset at the start of each epoch.
        self.true_positives.assign(0.0)


model = get_uncompiled_model()
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[CategoricalTruePositives()],
)
model.fit(x_train, y_train, batch_size=64, epochs=3)

结果如下:

处理不符合标准特征的损失和指标

绝大多数损失和度量指标都可以通过 y_true 和 y_pred 计算得出,其中 y_pred 是模型的输出,但并非所有损失和度量指标都可以通过 y_true 和 y_pred 计算得出。例如,正则化损失可能只需要激活一层(在这种情况下没有目标),而这种激活可能不是模型的输出。

在这种情况下,可以在自定义层的调用方法中调用 self.add_loss(loss_value)。以这种方式添加的损失会被添加到训练过程中的 "主 "损失(传递给 compile() 的损失)中。

下面是一个添加活动正则化的简单示例(请注意,所有 Keras 层都内置了活动正则化,本层只是为了提供一个具体示例):

class ActivityRegularizationLayer(layers.Layer):
    def call(self, inputs):
        self.add_loss(ops.sum(inputs) * 0.1)
        return inputs  # Pass-through layer.


inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)

# Insert activity regularization as a layer
x = ActivityRegularizationLayer()(x)

x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)

# The displayed loss will be much higher than before
# due to the regularization component.
model.fit(x_train, y_train, batch_size=64, epochs=1)

结果如下:

请注意,当通过 add_loss() 传递损失时,调用 compile() 时就可以不使用损失函数了,因为模型已经有了要最小化的损失。

请看下面的 LogisticEndpoint 层它将 targets 和 logits 作为输入,并通过 add_loss() 跟踪交叉熵损失。

class LogisticEndpoint(keras.layers.Layer):
    def __init__(self, name=None):
        super().__init__(name=name)
        self.loss_fn = keras.losses.BinaryCrossentropy(from_logits=True)

    def call(self, targets, logits, sample_weights=None):
        # Compute the training-time loss value and add it
        # to the layer using `self.add_loss()`.
        loss = self.loss_fn(targets, logits, sample_weights)
        self.add_loss(loss)

        # Return the inference-time prediction tensor (for `.predict()`).
        return ops.softmax(logits)

您可以在有两个输入(输入数据和目标)的模型中使用它,编译时不需要损失参数,就像这样

inputs = keras.Input(shape=(3,), name="inputs")
targets = keras.Input(shape=(10,), name="targets")
logits = keras.layers.Dense(10)(inputs)
predictions = LogisticEndpoint(name="predictions")(targets, logits)

model = keras.Model(inputs=[inputs, targets], outputs=predictions)
model.compile(optimizer="adam")  # No loss argument!

data = {
    "inputs": np.random.random((3, 3)),
    "targets": np.random.random((3, 10)),
}
model.fit(data)

演绎结果如下

自动分隔验证暂留集

在你看到的第一个端到端示例中,我们使用 validation_data 参数将 NumPy 数组(x_val、y_val)的元组传递给模型,以便在每个历时结束时评估验证损失和验证指标。

这里还有一个选项:参数 validation_split 可以自动保留部分训练数据用于验证。

例如,validation_split=0.2 表示 "使用 20% 的数据进行验证",validation_split=0.6 表示 "使用 60% 的数据进行验证"。


计算验证的方法是,在任何洗牌之前,从 fit() 调用收到的数组中提取最后 x% 的样本。

请注意,只有在使用 NumPy 数据训练时才能使用 validation_split。

model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)

演绎结果如下:

使用 tf.data 数据集进行培训和评估

在过去的几段中,我们已经了解了如何处理损失、度量值和优化器,还了解了当数据以 NumPy 数组形式传递时,如何在 fit() 中使用 validation_data 和 validation_split 参数。

另一种方法是使用类似迭代器的东西,比如 tf.data.Dataset、PyTorch DataLoader 或 Keras PyDataset。

tf.data API 是 TensorFlow 2.0 中的一组实用工具,用于以快速、可扩展的方式加载和预处理数据。

无论您使用的后端是 JAX、PyTorch 还是 TensorFlow,您都可以使用 tf.data 训练您的 Keras 模型。

您可以将 Dataset 实例直接传递给 fit()、evaluate() 和 predict() 方法

model = get_compiled_model()

# First, let's create a training Dataset instance.
# For the sake of our example, we'll use the same MNIST data as before.
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Now we get a test dataset.
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_dataset = test_dataset.batch(64)

# Since the dataset already takes care of batching,
# we don't pass a `batch_size` argument.
model.fit(train_dataset, epochs=3)

# You can also evaluate or predict on a dataset.
print("Evaluate")
result = model.evaluate(test_dataset)
dict(zip(model.metrics_names, result))

演绎结果如下

请注意,数据集会在每个轮次结束时重置,因此可以在下一个轮次重复使用。

如果只想在该数据集的特定批次上运行训练,可以传递 steps_per_epoch 参数,指定在进入下一个 epoch 之前,模型应使用该数据集运行多少训练步骤。

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Only use the 100 batches per epoch (that's 64 * 100 samples)
model.fit(train_dataset, epochs=3, steps_per_epoch=100)

结果如下

您也可以在 fit() 中传递 Dataset 实例作为 validation_data 参数

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)

model.fit(train_dataset, epochs=1, validation_data=val_dataset)

结果如下:

在每个历时结束时,模型将遍历验证数据集,并计算验证损失和验证指标

如果只想对该数据集的特定批次运行验证,可以传递 validation_steps 参数,指定在中断验证并进入下一个 epoch 之前,模型应使用验证数据集运行多少个验证步骤

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)

model.fit(
    train_dataset,
    epochs=1,
    # Only run validation using the first 10 batches of the dataset
    # using the `validation_steps` argument
    validation_data=val_dataset,
    validation_steps=10,
)

结果如下

请注意,每次使用后,验证数据集都会重置(这样您就可以始终在相同的样本上进行历时评估)

在使用数据集对象进行训练时,不支持参数 validation_split(从训练数据中生成保留集),因为该功能需要对数据集的样本进行索引,而数据集 API 一般无法做到这一点。


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

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

相关文章

pytorch+tensorboard

安装依赖 pip install teorboard pip install torch_tb_profiler了解teorboard 记录并可视化标量[组]、图片[组]。 如何使用 第一步:构建模型,记录中间值,写入summarywriter 每次写入一个标量add_scalar 比如: from torch.u…

深度学习:基于PyTorch的模型解释工具Captum

深度学习:基于PyTorch的模型解释工具Captum 引言简介示例安装解释模型的预测解释文本模型情绪分析问答 解释视觉模型特征分析特征消融鲁棒性 解释多模态模型 引言 当我们训练神经网络模型时,我们通常只关注模型的整体性能,例如准确率或损失函…

上位机图像处理和嵌入式模块部署(qmacvisual区域提取)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 在图像处理中,有两部分比较重要,一个是区域分割,一个是区域提取。区域分割,比较好理解,…

Chrome 插件 storage API 解析

Chrome.storage API 解析 使用 chrome.storage API 存储、检索和跟踪用户数据的更改 一、各模块中的 chrome.storage 内容 1. Service worker 中 runtime 内容 2. Action 中 runtime 内容 3. Content 中 runtime 内容 二、权限(Permissions) 如果需使…

SPU赋能PSI:探秘隐私集合求交核心技术与高级调度架构实践

1.SPU实现的PSI介绍 1.PSI的定义和种类 隐私集合求交(Private Set Intersection, PSI)是一种在密码学和安全多方计算(MPC)领域中的关键技术,允许两个或多个参与者在不泄露各自输入集合中非交集部分的前提下&#xff…

【python分析实战】成本:揭示电商平台月度开支与成本结构占比 - 过于详细 【收藏】

重点关注本文思路,用python分析,方便大家实验复现,代码每次都用全量的,其他工具自行选择。 全文3000字,阅读10min,操作1小时 企业案例实战欢迎关注专栏 每日更新:https://blog.csdn.net/cciehl/…

深入理解element-plus table二次封装:从理论到实践的全面指南

前言 在许多中后台管理系统中,表格占据着半壁江山,如果使用element plus组件库,那么少不了要用到table组件,可是table组件的功能过于基础,因此,我在table组件的实现基础之上进一步封装,从而实现…

2024-03-24 需求分析-智能问答系统-调研

一. 需求列表 基于本地知识库的问答系统对接外围系统 数字人语音识别二. 待调研的公司 2.1 音视贝 AI智能外呼_大模型智能客服系统_大模型知识库系统_杭州音视贝 (yinshibei.com) 2.2 得助智能 智能AI客服机器人-智能电话机器人客服-电话电销机器人-得助智能 (51ima.com) 2…

【LVGL-使用SquareLine Studio设计器 】

LVGL-使用SquareLine Studio设计器 ■ 简介■ 安装■ SquareLine Studio移植到工程 ■ 简介 SquareLine Studio 设计器是一个付费软件。 ■ 安装 SquareLine Studio 设计器的下载地址 我们点击“WINDOWS”下载 SquareLine Studio 设计器,下载完成之后我们就会得到…

ActiveMQ Artemis 系列| High Availability 主备模式(消息复制) 版本2.19.1

一、ActiveMQ Artemis 介绍 Apache ActiveMQ Artemis 是一个高性能的开源消息代理,它完全符合 Java Message Service (JMS) 2.0 规范,并支持多种通信协议,包括 AMQP、MQTT、STOMP 和 OpenWire 等。ActiveMQ Artemis 由 Apache Software Foun…

Android 性能优化实例分享-内存优化 兼顾效率与性能

背景 项目上线一段时间后,回顾重要页面 保证更好用户体验及生产效率,做了内存优化和下载导出优化,具体效果如最后的一节的表格所示。 下面针对拍摄流程的两个页面 预览页 导出页优化实例进行介绍: 一.拍摄前预览页面优化 预览效果问题 存在…

快速上手Spring Cloud 十一:微服务架构下的安全与权限管理

快速上手Spring Cloud 一:Spring Cloud 简介 快速上手Spring Cloud 二:核心组件解析 快速上手Spring Cloud 三:API网关深入探索与实战应用 快速上手Spring Cloud 四:微服务治理与安全 快速上手Spring Cloud 五:Spring …

vuees6新语法

vue的学习网站: https://www.runoob.com/vue2/vue-tutorial.html1.Vue的介绍 学习目标 说出什么是Vue能够说出Vue的好处能够说出Vue的特点 内容讲解 【1】Vue介绍 1.vue属于一个前端框架,底层使用原生js编写的。主要用来进行前端和后台服务器之间的…

搜索插入位置-java

题目描述 : 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。 思路分析: 这段代码的解题思想是利用二分查找的方法在…

微服务(基础篇-006-Docker安装-CentOS7)

目录 05-初识Docker-Docker的安装_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1LQ4y127n4?p46&spm_id_frompageDriver&vd_source60a35a11f813c6dff0b76089e5e138cc 0.安装Docker 1.CentOS安装Docker 1.1.卸载(可选) 1.2.安装dock…

爬虫工作量由小到大的思维转变---<第六十章 Scrapy框架中的信号处理机制(Signals)研究(1)>

前言: Scrapy框架默认的事件驱动设计在某些场景下可能不够灵活或满足定制化需求。因此,深入研究Scrapy框架中的信号处理机制(Signals)是必要的。 本研究的目的是深入了解Scrapy框架中的信号处理机制,在网络爬虫中的应用和意义。通…

软考高级架构师:ESB 企业服务总线概念和例题

作者:明明如月学长, CSDN 博客专家,大厂高级 Java 工程师,《性能优化方法论》作者、《解锁大厂思维:剖析《阿里巴巴Java开发手册》》、《再学经典:《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

正则表达式 vs. 字符串处理:解析优势与劣势

title: 正则表达式 vs. 字符串处理:解析优势与劣势 date: 2024/3/27 15:58:40 updated: 2024/3/27 15:58:40 tags: 正则起源正则原理模式匹配优劣分析文本处理性能比较编程应用 1. 正则表达式起源与演变 正则表达式(Regular Expression)最早…

单链表交叉分离,运用头插法,尾插法(算法库应用)

原文博客链接:单链表分离(头插法和尾插法的结合,理解指针变换)_3.对任务1或者2中创建的某一个单链表{a1,b1,a2,b2,...,an,bn},编写一个算法将-CSDN博客 函数实现: /************************************************** 函数名:separate_LinkList 功 能: 把一个链表,交叉新建…

风力发电电网系统的simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1风力发电原理与风机数学模型 4.2 电力电子变换器模型 4.3并网控制策略 5.完整工程文件 1.课题概述 风力发电电网系统的simulink建模与仿真。 2.系统仿真结果 3.核心程序与模型 版本:…