《深度学习实战》第3集:循环神经网络(RNN)与序列建模

第3集:循环神经网络(RNN)与序列建模


引言

在深度学习领域,处理序列数据(如文本、语音、时间序列等)是一个重要的研究方向。传统的全连接网络和卷积神经网络(CNN)难以直接捕捉序列中的时序依赖关系,而循环神经网络(Recurrent Neural Network, RNN)应运而生。它通过引入“记忆”机制,能够有效建模序列数据的动态特性。然而,随着任务复杂度的提升,RNN 的局限性也逐渐显现,这促使了 LSTM 和 GRU 等改进模型的诞生。本集将深入探讨 RNN 的基本原理及其改进版本,并结合实战项目展示其应用价值。最后,我们还将讨论 Transformer 如何逐步取代 RNN 成为序列建模的新宠。


1. RNN 的基本原理与局限性

1.1 什么是 RNN?

RNN(Recurrent Neural Network)是一类适合处理序列数据的神经网络。与传统的前馈神经网络不同,RNN具有循环结构,可以将前一个时刻的信息传递到当前时刻,从而记忆序列中的历史信息。

RNN的工作原理:

  • 在每个时间步,RNN通过接收当前输入和上一时刻的隐藏状态,更新当前的隐藏状态,并计算当前的输出。
  • 这种结构允许RNN处理具有时序依赖关系的数据,如语音、文本和时间序列。

基本原理
RNN 的核心思想是通过一个循环结构,将当前时刻的输入与上一时刻的隐藏状态结合起来,从而实现对序列信息的记忆。具体来说,RNN 的计算公式如下:

h t = σ ( W h h t − 1 + W x x t + b ) h_t = \sigma(W_h h_{t-1} + W_x x_t + b) ht=σ(Whht1+Wxxt+b)

其中:

  • h t 是当前时刻的隐藏状态; h_t 是当前时刻的隐藏状态; ht是当前时刻的隐藏状态;
  • x t 是当前时刻的输入; x_t 是当前时刻的输入; xt是当前时刻的输入;
  • W h 和 W x 是权重矩阵; W_h 和 W_x 是权重矩阵; WhWx是权重矩阵;
  • b 是偏置项; b 是偏置项; b是偏置项;
  • σ 是激活函数(通常为 t a n h 或 R e L U )。 \sigma 是激活函数(通常为 tanh 或 ReLU)。 σ是激活函数(通常为tanhReLU)。

通过这种递归计算,RNN 能够捕捉序列中的时序依赖关系。

局限性
尽管 RNN 在理论上可以处理任意长度的序列,但在实际训练中存在以下问题:

  1. 梯度消失/爆炸问题:由于反向传播过程中梯度需要通过时间维度传递,长序列会导致梯度指数级缩小或放大。当序列较长时,RNN的梯度容易在反向传播过程中消失或爆炸,使得模型难以学习长期依赖关系
  2. 长期依赖问题:RNN 难以记住距离较远的信息,因为隐藏状态会随着时间被覆盖或遗忘。RNN在捕捉较长时间依赖时效果较差,尤其是在长序列中,它无法保持足够的信息。

这些问题限制了 RNN 在复杂任务中的表现。


1.2 LSTM 和 GRU 的改进

为了克服 RNN 的局限性,研究者提出了两种改进模型:LSTM(Long Short-Term Memory)长短期记忆网络和 GRU(Gated Recurrent Unit)门控循环单元。它们通过引入门控机制,增强了模型对长期依赖的建模能力。

  • LSTM(长短期记忆网络)
    在这里插入图片描述

LSTM通过引入“记忆单元”和“门控机制”来控制信息流动,克服了传统RNN在长时间序列建模中的不足。LSTM的核心组件包括:

  • 遗忘门:决定当前时间步的记忆单元中哪些信息需要遗忘。
  • 输入门:控制当前时间步的输入信息如何更新到记忆单元中。
  • 输出门:控制记忆单元的信息如何影响输出。

通过这些门控机制,LSTM能够有效地保持长期依赖信息,避免梯度消失问题。

  • GRU(门控循环单元)
    在这里插入图片描述

GRU是LSTM的简化版本,它将LSTM中的遗忘门和输入门合并为一个更新门,减少了参数量,使得训练更加高效。GRU的结构较LSTM更为简单,但在很多任务上,GRU与LSTM的表现相差不大。

LSTM 公式解释
LSTM 引入了三个门(输入门、遗忘门、输出门)以及一个细胞状态(cell state),用于控制信息的流动。其核心公式如下:

  1. 遗忘门:决定哪些信息需要从细胞状态中丢弃。
    f t = σ ( W f ⋅ [ h t − 1 , x t ] + b f ) f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f) ft=σ(Wf[ht1,xt]+bf)

  2. 输入门:决定哪些新信息需要添加到细胞状态中。
    i t = σ ( W i ⋅ [ h t − 1 , x t ] + b i ) i_t = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) it=σ(Wi[ht1,xt]+bi)
    C ~ t = tanh ⁡ ( W C ⋅ [ h t − 1 , x t ] + b C ) \tilde{C}_t = \tanh(W_C \cdot [h_{t-1}, x_t] + b_C) C~t=tanh(WC[ht1,xt]+bC)

  3. 更新细胞状态
    C t = f t ⊙ C t − 1 + i t ⊙ C ~ t C_t = f_t \odot C_{t-1} + i_t \odot \tilde{C}_t Ct=ftCt1+itC~t

  4. 输出门:决定当前时刻的隐藏状态。
    o t = σ ( W o ⋅ [ h t − 1 , x t ] + b o ) o_t = \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) ot=σ(Wo[ht1,xt]+bo)
    h t = o t ⊙ tanh ⁡ ( C t ) h_t = o_t \odot \tanh(C_t) ht=ottanh(Ct)

GRU公式解释
GRU 是 LSTM 的简化版本,将遗忘门和输入门合并为更新门,并移除了单独的细胞状态。其核心公式如下:

  1. 更新门
    z t = σ ( W z ⋅ [ h t − 1 , x t ] + b z ) z_t = \sigma(W_z \cdot [h_{t-1}, x_t] + b_z) zt=σ(Wz[ht1,xt]+bz)

  2. 重置门
    r t = σ ( W r ⋅ [ h t − 1 , x t ] + b r ) r_t = \sigma(W_r \cdot [h_{t-1}, x_t] + b_r) rt=σ(Wr[ht1,xt]+br)

  3. 候选隐藏状态
    h ~ t = tanh ⁡ ( W ⋅ [ r t ⊙ h t − 1 , x t ] + b ) \tilde{h}_t = \tanh(W \cdot [r_t \odot h_{t-1}, x_t] + b) h~t=tanh(W[rtht1,xt]+b)

  4. 最终隐藏状态
    h t = ( 1 − z t ) ⊙ h t − 1 + z t ⊙ h ~ t h_t = (1 - z_t) \odot h_{t-1} + z_t \odot \tilde{h}_t ht=(1zt)ht1+zth~t

LSTM 和 GRU 的门控机制使得它们能够更好地捕捉长期依赖关系,同时缓解了梯度消失问题。


1.3 序列建模的应用场景

RNN 及其变体广泛应用于以下领域:

  1. 语言建模:语言建模是自然语言处理中的一个重要任务,目标是根据前文的单词预测下一个单词。RNN、LSTM和GRU在语言建模中表现优异,能够捕捉句子中各个单词之间的时序依赖关系,可预测下一个单词的概率分布,常用于机器翻译、文本生成等任务。
  2. 时间序列预测:时间序列预测是使用历史数据预测未来的一个典型应用场景。例如,在股票市场中,我们希望基于历史价格数据预测未来的股价趋势。RNN、LSTM和GRU被广泛应用于金融领域的时间序列预测任务,也常用于天气预测等领域。
  3. 语音识别:将音频信号转化为文本。
  4. 视频分析:捕捉视频帧之间的时序关系。

2. 实战项目:使用 LSTM 预测股票价格趋势

2.1 项目背景

我们将使用LSTM模型来预测股票价格趋势。数据来源于Yahoo Finance,我们将使用过去的股票数据来预测未来几天的股票价格变化。

2.2 数据准备

首先,安装所需的库:

pip install yfinance pandas numpy matplotlib tensorflow scikit-learn

接着,获取股票数据并进行预处理:

import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler

# 获取股票数据
data = yf.download('AAPL', start='2010-01-01', end='2023-01-01', auto_adjust=True)

# 使用收盘价
closing_prices = data['Close'].values.reshape(-1, 1)

# 数据归一化
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(closing_prices)

# 创建训练数据(使用过去60天的数据预测下一天的价格)
def create_dataset(data, time_step=60):
    X, y = [], []
    for i in range(len(data)-time_step-1):
        X.append(data[i:(i+time_step), 0])
        y.append(data[i + time_step, 0])
    return np.array(X), np.array(y)

X, y = create_dataset(scaled_data)

# 重塑输入数据的形状为 [样本数, 时间步长, 特征数]
X = X.reshape(X.shape[0], X.shape[1], 1)

# 划分训练集和测试集
train_size = int(len(X) * 0.8)
X_train, X_test = X[:train_size], X[train_size:]
y_train, y_test = y[:train_size], y[train_size:]

2.3 构建LSTM模型

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout

# 构建LSTM模型
model = Sequential()
model.add(LSTM(units=50, return_sequences=True, input_shape=(X_train.shape[1], 1)))
model.add(Dropout(0.2))
model.add(LSTM(units=50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(units=1))

# 编译模型
model.compile(optimizer='adam', loss='mean_squared_error')

# 训练模型
model.fit(X_train, y_train, epochs=10, batch_size=32)

2.4 预测与可视化

# 使用模型进行预测
predictions = model.predict(X_test)

# 反归一化预测结果
predictions = scaler.inverse_transform(predictions)
y_test = scaler.inverse_transform(y_test.reshape(-1, 1))

# 可视化结果
plt.figure(figsize=(12, 6))
plt.plot(y_test, color='blue', label='Actual Stock Price')
plt.plot(predictions, color='red', label='Predicted Stock Price')
plt.title('Stock Price Prediction using LSTM')
plt.xlabel('Time')
plt.ylabel('Stock Price')
plt.legend()
plt.show()

** 代码汇总:**

import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler

# 获取股票数据
data = yf.download('AAPL', start='2010-01-01', end='2023-01-01', auto_adjust=True)


if data.empty:
    print("No data found, check the stock symbol or try again later.")
else:

    # 使用收盘价
    closing_prices = data['Close'].values.reshape(-1, 1)

    # 数据归一化
    scaler = MinMaxScaler(feature_range=(0, 1))
    scaled_data = scaler.fit_transform(closing_prices)

    # 创建训练数据(使用过去60天的数据预测下一天的价格)
    def create_dataset(data, time_step=60):
        X, y = [], []
        for i in range(len(data)-time_step-1):
            X.append(data[i:(i+time_step), 0])
            y.append(data[i + time_step, 0])
        return np.array(X), np.array(y)

    X, y = create_dataset(scaled_data)

    # 重塑输入数据的形状为 [样本数, 时间步长, 特征数]
    X = X.reshape(X.shape[0], X.shape[1], 1)

    # 划分训练集和测试集
    train_size = int(len(X) * 0.8)
    X_train, X_test = X[:train_size], X[train_size:]
    y_train, y_test = y[:train_size], y[train_size:]


    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import LSTM, Dense, Dropout

    # 构建LSTM模型
    model = Sequential()
    model.add(LSTM(units=50, return_sequences=True, input_shape=(X_train.shape[1], 1)))
    model.add(Dropout(0.2))
    model.add(LSTM(units=50, return_sequences=False))
    model.add(Dropout(0.2))
    model.add(Dense(units=1))

    # 编译模型
    model.compile(optimizer='adam', loss='mean_squared_error')

    # 训练模型
    model.fit(X_train, y_train, epochs=10, batch_size=32)

    # 使用模型进行预测
    predictions = model.predict(X_test)

    # 反归一化预测结果
    predictions = scaler.inverse_transform(predictions)
    y_test = scaler.inverse_transform(y_test.reshape(-1, 1))

    # 可视化结果
    plt.figure(figsize=(12, 6))
    plt.plot(y_test, color='blue', label='Actual Stock Price')
    plt.plot(predictions, color='red', label='Predicted Stock Price')
    plt.title('Stock Price Prediction using LSTM')
    plt.xlabel('Time')
    plt.ylabel('Stock Price')
    plt.legend()
    plt.show()

代码输出结果:

[*********************100%***********************]  1 of 1 completed
2025-02-25 22:43:23.883004: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
2025-02-25 22:43:26.821365: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
2025-02-25 22:43:29.733373: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
D:\python_projects\lstm_demo\Lib\site-packages\keras\src\layers\rnn\rnn.py:200: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.
  super().__init__(**kwargs)
Epoch 1/10
81/81 ━━━━━━━━━━━━━━━━━━━━ 4s 19ms/step - loss: 0.0037
Epoch 2/10
81/81 ━━━━━━━━━━━━━━━━━━━━ 2s 19ms/step - loss: 3.0320e-04
Epoch 3/10
81/81 ━━━━━━━━━━━━━━━━━━━━ 2s 19ms/step - loss: 2.5178e-04
Epoch 4/10
81/81 ━━━━━━━━━━━━━━━━━━━━ 2s 19ms/step - loss: 2.8054e-04
Epoch 5/10
81/81 ━━━━━━━━━━━━━━━━━━━━ 2s 19ms/step - loss: 2.1884e-04
Epoch 6/10
81/81 ━━━━━━━━━━━━━━━━━━━━ 2s 19ms/step - loss: 1.9784e-04
Epoch 7/10
81/81 ━━━━━━━━━━━━━━━━━━━━ 2s 19ms/step - loss: 1.7942e-04
Epoch 8/10
81/81 ━━━━━━━━━━━━━━━━━━━━ 2s 19ms/step - loss: 1.9470e-04
Epoch 9/10
81/81 ━━━━━━━━━━━━━━━━━━━━ 2s 19ms/step - loss: 1.5350e-04
Epoch 10/10
81/81 ━━━━━━━━━━━━━━━━━━━━ 2s 19ms/step - loss: 2.8230e-04
21/21 ━━━━━━━━━━━━━━━━━━━━ 1s 16ms/step

输出预测对比图片:
在这里插入图片描述

2.5 图解RNN和LSTM

  1. RNN 展开图

    在这里插入图片描述
    在这里插入图片描述

  2. LSTM 单元结构
    ( LSTM 单元结构图,标注输入门、遗忘门、输出门和细胞状态。)
    在这里插入图片描述


3. 前沿关联:Transformer 在序列建模中的崛起

尽管LSTM和GRU在序列建模中取得了显著成果,但随着Transformer模型的出现,序列建模的格局发生了变化。Transformer模型通过自注意力机制能够并行处理序列数据,且在处理长距离依赖时更加高效。如今,Transformer模型已广泛应用于自然语言处理任务,如BERT和GPT系列模型。Transformer 模型凭借其自注意力机制(Self-Attention)彻底改变了序列建模领域。相比于 RNN,Transformer 具有以下优势:

  1. 并行化训练:无需按时间顺序处理序列,大幅提高了训练效率。
  2. 长程依赖建模:自注意力机制能够直接捕捉全局依赖关系。
  3. 广泛应用:Transformer 已成为 GPT、BERT 等大模型的核心架构。

尽管如此,RNN 仍然在某些特定任务(如实时序列处理)中具有不可替代的价值。理解 RNN 的原理及其改进版本,有助于我们更好地掌握现代深度学习技术的发展脉络。


总结

本集聚焦于循环神经网络(RNN)的基本原理及其改进模型 LSTM 和 GRU,并通过实战项目展示了它们在时间序列预测中的应用。同时,我们也探讨了 Transformer 的崛起如何推动序列建模进入新时代。下一集,我们将深入探讨 Transformer 的工作原理及其在自然语言处理中的革命性应用。敬请期待!


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

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

相关文章

10.【线性代数】—— 四个基本子空间

十、 四个基本子空间 1. 列空间 C ( A ) C(A) C(A) in R m R^m Rm2. 零空间 N ( A ) N(A) N(A) in R n R^n Rn3. 行空间 C ( A T ) C(A^T) C(AT) in R n R^n Rn4. 左零空间 N ( A T ) N(A^T) N(AT) in R m R^m Rm综述5. 新的向量空间 讨论矩阵 A m ∗ n A_{m*n} Am∗n​…

Windows上使用go-ios实现iOS17自动化

前言 在Windows上运行iOS的自动化,tidevice对于iOS17以上并不支持,原因是iOS 17 引入新通信协议 ‌RemoteXPCQUIC‌,改变了 XCUITest 的启动方式。 一、go-ios的安装 1、安装命令:npm i go-ios 2、安装完成后输入命令which io…

CBAM注意力机制详解与实现

前言: 在深度学习领域,注意力机制已成为提升模型性能的重要手段之一。CBAM(Convolutional Block Attention Module)作为一种轻量级且高效的注意力机制,被广泛应用于各种卷积神经网络中。 一、CBAM注意力机制概述 1.…

GCN从理论到实践——基于PyTorch的图卷积网络层实现

Hi,大家好,我是半亩花海。图卷积网络(Graph Convolutional Network, GCN)是一种处理图结构数据的深度学习模型。它通过聚合邻居节点的信息来更新每个节点的特征表示,广泛应用于社交网络分析、推荐系统和生物信息学等领…

给虚拟机配置IP

虚拟机IP这里一共有三个地方要设置,具体说明如下: (1)配置vm虚拟机网段 如果不进行设置,每次启动机器时都可能是随机的IP,不方便我们后续操作。具体操作是:点击编辑→虚拟网络编辑器 选择VMne…

【免费】YOLO[笑容]目标检测全过程(yolo环境配置+labelimg数据集标注+目标检测训练测试)

一、yolo环境配置 这篇帖子是我试过的,非常全,很详细【cudaanacondapytorchyolo(ultralytics)】 yolo环境配置 二、labelimg数据集标注 可以参考下面的帖子,不过可能会出现闪退的问题,安装我的流程来吧 2.1 labelimg安装 label…

mapbox基础,使用geojson加载heatmap热力图层

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️heatmap热力图层样式二、🍀使用geojs…

Python 课堂点名桌面小程序

一、场景分析 闲来无事,老婆说叫我开发一个课堂点名桌面小程序,给她在课堂随机点名学生问问题。 人生苦短,那就用 Python 给她写一个吧。 二、依赖安装 因为要用到 excel,所以安装两个依赖: pip install openpyxl…

蓝桥杯 路径之谜

路径之谜 题目描述 小明冒充 XX 星球的骑士,进入了一个奇怪的城堡。 城堡里边什么都没有,只有方形石头铺成的地面。 假设城堡地面是 nnnn 个方格。如下图所示。 按习俗,骑士要从西北角走到东南角。可以横向或纵向移动,但不能斜着走…

在鸿蒙HarmonyOS手机上安装hap应用

一、下载工具 安装hap包需要用到小工具 。 二、解压到目录后,进入该文件夹,打开命令行,如下图 三、将下载好的hap包放入刚才解压的文件夹内(假设hap包文件名为app.hap) 四、连接好手机和电脑,手机需要打…

Android APK组成编译打包流程详解

Android APK(Android Package)是 Android 应用的安装包文件,其组成和打包流程涉及多个步骤和文件结构。以下是详细的说明: 一、APK 的组成 APK 是一个 ZIP 格式的压缩包,包含应用运行所需的所有文件。解压后主要包含以…

自然语言处理:词频-逆文档频率

介绍 大家好,博主又来给大家分享知识了。本来博主计划完成稠密向量表示的内容分享后,就开启自然语言处理中文本表示的讲解。可在整理分享资料的时候,博主发现还有个知识点,必须得单独拎出来好好说道说道。 这就是TF-IDF&#xf…

esp8266 rtos sdk开发环境搭建

1. 安装必要的工具 1.1 安装 Git Git 用于从远程仓库克隆代码,你可以从Git 官方网站下载 Windows 版本的安装程序。安装过程中可保持默认设置,安装完成后,在命令提示符(CMD)或 PowerShell 中输入git --version&#…

pytest下放pytest.ini文件就导致报错:ERROR: file or directory not found: #

pytest下放pytest.ini文件就导致报错:ERROR: file or directory not found: # 如下: 项目文件目录如下: pytest.ini文件内容: [pytest] addopts -v -s --alluredir ./allure-results # 自动添加的命令行参数:# -…

Blender调整最佳渲染清晰度

1.渲染采样调高 512 2.根据需要 开启AO ,开启辉光 , 开启 屏幕空间反射 3.调高分辨率 4096x4096 100% 分辨率是清晰度的关键 , 分辨率不高 , 你其他参数调再高都没用 4.世界环境开启体积散射 , 可以增强氛围感 5.三点打光法 放在模型和相机45夹角上 白模 白模带线条 成品

Vllm进行Qwen2-vl部署(包含单卡多卡部署及爬虫请求)

1.简介 阿里云于今年9月宣布开源第二代视觉语言模型Qwen2-VL,包括 2B、7B、72B三个尺寸及其量化版本模型。Qwen2-VL具备完整图像、多语言的理解能力,性能强劲。 相比上代模型,Qwen2-VL 的基础性能全面提升,可以读懂不同分辨率和…

xr-frame 3D Marker识别,扬州古牌坊 3D识别技术稳定调研

目录 识别物体规范 3D Marker 识别目标文件 map 生成 生成任务状态解析 服务耗时: 对传入的视频有如下要求: 对传入的视频建议: 识别物体规范 为提高Marker质量,保证算法识别效果,可参考Marker规范文档 Marker规…

Windows环境下SuperMapGIS 11i 使用达梦数据库

1. 环境介绍: 1.1. 操作系统: windows server 2019 1.2. GIS 软件: 1.2.1. GIS 桌面 supermap-idesktopx-11.3.0-windows-x64-bin 下载链接:SuperMap技术资源中心|为您提供全面的在线技术服务 安装教程:绿色版&…

redis的下载和安装详解

一、下载redis安装包 进入redis官网查看当前稳定版本: https://redis.io/download/发现此时的稳定版本是6.2.4, 此时可以去这个网站下载6.2.4稳定版本的tar包。 暂时不考虑不在windows上使用redis,那样将无法发挥redis的性能 二、上传tar…

Prometheus + Grafana 监控

Prometheus Grafana 监控 官网介绍:Prometheus 是一个开源系统 监控和警报工具包最初由 SoundCloud 构建。自 2012 年成立以来,许多 公司和组织已经采用了 Prometheus,并且该项目具有非常 活跃的开发人员和用户社区。它现在是一个独立的开源…