基于金融产品深度学习推荐算法详解【附源码】
深度学习算法说明
1、简介
神经网络协同过滤模型(NCF)
为了解决启发式推荐算法的问题,基于神经网络的协同过滤算法诞生了,神经网络的协同过滤算法可以
通过将用户和物品的特征向量作为输入,来预测用户对新物品的评分,从而解决冷启动问题。
对数据稀疏性的鲁棒性:神经网络的协同过滤算法可以自动学习用户和物品的特征向量,并能够通过这
些向量来预测评分,因此对于数据稀疏的情况也能进行有效的预测。
更好的预测准确率:神经网络的协同过滤算法可以通过多层非线性变换来学习用户和物品之间的复杂关
系,从而能够提高预测准确率。
可解释性和灵活性:神经网络的协同过滤算法可以通过调整网络结构和参数来优化预测准确率,并且可
以通过可视化方法来解释预测结果。
所以基于神经网络协同过滤模型是目前推荐系统的主流形态。
2、安装库
pip install numpy
pip install pandas
pip install tensorflow
3、流程
1、构造数据矩阵(从用户评分表中加载所有用户的评分数据。)
2、数据预处理:把数据向量化,便于神经网络计算
3、对数据进行打标签操作
4、定义64个维度针对向量进行处理(神经网络是非线性多维度)
5、创建NCF模型
6、合并 embeddings向量
7、添加全连接层
8、编译模型
9、模型评估
10、模型保存
4、代码
# -*-coding:utf-8-*-"""
@contact: 微信 1257309054
@file: 深度学习推荐算法.py
@time: 2025/3/17 21:30
@author: LDC
"""
import osimport django
from django.conf import settingsos.environ["DJANGO_SETTINGS_MODULE"] = "finance_manager.settings"
django.setup()import joblib
import matplotlib.pyplot as plt
import pymysql
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report
import tensorflow as tf
from keras.layers import Input, Embedding, Flatten, Dense, Concatenate
from keras.models import Model
from keras.src.layers import Dropout
from finance.models import UserSelectTypes, LikeRecommendfinance, Finances, RateFinance# normalized for 中文显示和负号
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = Falsedef get_data():'''从数据库获取数据'''conn = pymysql.connect(host=settings.DATABASE_HOST,user=settings.DATABASE_USER,password=settings.DATABASE_PASS,database=settings.DATABASE_NAME,charset='utf8mb4',use_unicode=True)sql_cmd = 'SELECT user_id, finance_id, mark FROM rate_finance'dataset = pd.read_sql(sql=sql_cmd, con=conn)conn.close() # 使用完后记得关掉return dataset# ==================== 数据生成与预处理 ====================
def generate_data():"""获取数据集"""np.random.seed(42)df = get_data()df, finance_map_dict, user_id_map_dict = preprocessing(df) # 数据预处理# 转换为二分类问题(假设>=3分为正样本)df['label'] = (df['mark'] >= 3).astype(int)n_users = len(df.user_id.unique()) # 统计用户数量n_finances = len(df.finance_id.unique()) # 统计产品数量num_samples = len(df) # 统计总样本数量return df, n_users, n_finances, num_samplesdef preprocess_data(df):"""数据预处理"""# 编码类别特征user_encoder = LabelEncoder()product_encoder = LabelEncoder()df['user_encoded'] = user_encoder.fit_transform(df['user_id'])df['product_encoded'] = product_encoder.fit_transform(df['finance_id'])# 划分特征和标签X = df[['user_encoded', 'product_encoded']]y = df['label']# 分割数据集X_train, X_test, y_train, y_test = train_test_split(X, y,test_size=0.2,random_state=42,stratify=y # 保持类别分布)return X_train, X_test, y_train, y_test# ==================== 模型构建 ====================
def build_model(num_users, num_products, embedding_dim, dropout_rate):"""构建深度学习模型"""# 输入层user_input = Input(shape=(1,), name='user_input')product_input = Input(shape=(1,), name='product_input')# 嵌入层user_embedding = Embedding(input_dim=num_users + 1,output_dim=embedding_dim,name='user_embedding')(user_input)product_embedding = Embedding(input_dim=num_products + 1,output_dim=embedding_dim,name='product_embedding')(product_input)# 合并特征merged = Concatenate()([Flatten()(user_embedding),Flatten()(product_embedding)])# 全连接层dense = Dense(128, activation='relu')(merged)dense = Dropout(dropout_rate)(dense)dense = Dense(64, activation='relu')(dense)dense = Dropout(dropout_rate)(dense)# 输出层output = Dense(1, activation='sigmoid')(dense)# 构建模型model = Model(inputs=[user_input, product_input], outputs=output)return model# ==================== 主程序 ====================
def main():# ==================== 配置参数 ====================# 模型参数embedding_dim = 64 # 嵌入维度dropout_rate = 0.3 # 防止过拟合THRESHOLD = 0.5 # 分类阈值# 训练参数EPOCHS = 15 # 训练轮数BATCH_SIZE = 128VALIDATION_SPLIT = 0.1# 生成并预处理数据df, num_users, num_products, num_samples = generate_data()X_train, X_test, y_train, y_test = preprocess_data(df)# 构建模型model = build_model(num_users, num_products, embedding_dim, dropout_rate)# 编译模型model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),loss='binary_crossentropy',metrics=['accuracy',tf.keras.metrics.Precision(name='precision'),tf.keras.metrics.Recall(name='recall'),])# 处理类别不平衡class_weights = {0: (1 / (len(y_train) - sum(y_train))) * (len(y_train) / 2.0),1: (1 / sum(y_train)) * (len(y_train) / 2.0)}# 训练模型history = model.fit([X_train['user_encoded'], X_train['product_encoded']],y_train,epochs=EPOCHS,batch_size=BATCH_SIZE,validation_split=VALIDATION_SPLIT,class_weight=class_weights,verbose=1)# 模型评估print("\n模型评估结果:")y_pred = (model.predict([X_test['user_encoded'], X_test['product_encoded']]) > THRESHOLD).astype(int)report = classification_report(y_test, y_pred, output_dict=True, target_names=['低评分', '高评分'])weighted_avg = report['weighted avg']accuracy = round(report['accuracy'], 3) # 准确率precision = round(weighted_avg['precision'], 3) # 精准度recall = round(weighted_avg['recall'], 3) # 召回率f1_score = round(weighted_avg['f1-score'], 3) # F1-scoreprint(report)print('准确率是{},精准度是{},召回率是{},F1值是{}'.format(accuracy, precision, recall, f1_score))# 训练过程可视化plt.figure(figsize=(15, 6))# 损失曲线plt.subplot(1, 1, 1)plt.plot(history.history['loss'], label='训练集损失')plt.plot(history.history['val_loss'], label='验证集损失')plt.title('损失变化曲线')plt.xlabel('Epoch')plt.ylabel('Loss')plt.legend()plt.show()# # 指标曲线# plt.subplot(1, 2, 2)# for metric in ['precision', 'recall']:# plt.plot(history.history[metric], label=f'训练集 {metric}')# plt.plot(history.history[f'val_{metric}'], linestyle='--', label=f'验证集 {metric}')# plt.title('指标变化曲线')# plt.xlabel('Epoch')# plt.ylabel('Score')# plt.legend()# plt.tight_layout()# plt.show()x = ['准确率', '精确度', '召回率', 'f1_score']plt.subplot(1, 1, 1)plt.title('模型指标')plt.plot(x, [accuracy, precision, recall, f1_score], c='blue', marker='o', linestyle=':', label='深度学习')# 图例展示位置,数字代表第几象限plt.legend(loc=4)plt.show()# 保存模型joblib.dump(model, 'user_product_model.h5')# model.save('user_product_model.h5')print("模型已保存为 user_product_model.h5")def predict(user_id, dataset):'''将预测评分高的产品推荐给该用户user_id'''try:# model = load_model('user_product_model.h5')model = joblib.load('user_product_model.h5')'''先拿到所有的产品索引ISBN,并去重成为finance_data。再添加一个和finance_data长度相等的用户列表user,不过这里的user列表中的元素全是1,因为我们要做的是:预测第1个用户对所有产品的评分,再将预测评分高的产品推荐给该用户。'''finance_data = np.array(list(set(dataset.finance_id)))user = np.array([user_id for i in range(len(finance_data))])predictions = model.predict([user, finance_data])# 更换列->行predictions = np.array([a[0] for a in predictions])# 根据原array,取其中数值从大到小的索引,再只取前top10recommended_finance_ids = (-predictions).argsort()[:10]print(recommended_finance_ids)print(predictions[recommended_finance_ids])return recommended_finance_idsexcept Exception as e:print('预测报错', e)return []def get_select_tag_finance(user_id, finance_id=None):# 获取用户注册时选择的产品类别各返回10门产品category_ids = []us = UserSelectTypes.objects.get(user_id=user_id)for category in us.category.all():category_ids.append(category.id)unlike_finance_ids = [d['finance_id'] for d inLikeRecommendfinance.objects.filter(user_id=user_id, is_like=0).values('finance_id')]if finance_id and finance_id not in unlike_finance_ids:unlike_finance_ids.append(finance_id)finance_list = Finances.objects.filter(category__in=category_ids).exclude(id__in=unlike_finance_ids).distinct().order_by("-like_num")[:10]return finance_listdef preprocessing(dataset):'''数据预处理把评分数据映射成用户字典,产品字典'''finance_val_counts = dataset.finance_id.value_counts()finance_map_dict = {}for i in range(len(finance_val_counts)):finance_map_dict[finance_val_counts.index[i]] = i# print(map_dict)dataset["finance_id"] = dataset["finance_id"].map(finance_map_dict)user_id_val_counts = dataset.user_id.value_counts()# 映射字典user_id_map_dict = {}for i in range(len(user_id_val_counts)):user_id_map_dict[user_id_val_counts.index[i]] = i# 将User_ID映射到一串字典dataset["user_id"] = dataset["user_id"].map(user_id_map_dict)return dataset, finance_map_dict, user_id_map_dictdef embedding_main(user_id, finance_id=None, is_rec_list=False):'''1、获取用户评分大于等于3的产品数据2、数据预处理:把数据映射成用户向量Embedding,产品向量Embedding3、划分训练集与测试集:使用二八法则随机划分,80%的数据用来训练,20%的数据用来测试4、训练模型:分别Emmbeding两个向量,再Concat连接起来,最后加上3个全连接层构成模型,进行训练5、模型评估:通过查看训练集损失函数来查看模型优劣6、预测推荐:对用户评分过的产品进行模型预测,把预测评分高的产品推荐给用户user_id: 用户idfinance_id: 用户已经评分过的产品id,需要在推荐列表中去除is_rec_list: 值为True:返回推荐[用户-评分]列表,值为False:返回推荐的产品列表'''dataset = get_data() # 获取数据# print(dataset.head())if user_id not in dataset.user_id.unique():# 用户未进行评分则推荐注册时选择的产品类型print('用户未进行评分则推荐注册时选择的产品类型')if is_rec_list:return []# 推荐列表为空,按用户注册时选择的产品类别各返回10门return get_select_tag_finance(user_id, finance_id)dataset, finance_map_dict, user_id_map_dict = preprocessing(dataset)# user_id需要转换为映射后的user_id传到predict函数中predict_finance_ids = predict(user_id_map_dict[user_id], dataset) # 预测的产品Idrecommend_list = [] # 最后推荐的产品id# 把映射的值转为真正的产品idfor finance_id in predict_finance_ids:for k, v in finance_map_dict.items():if finance_id == v:recommend_list.append(k)print('keras_recommended_finance_ids深度学习推荐列表', recommend_list)if not recommend_list:# 推荐列表为空,且is_rec_list: 值为True:返回推荐[用户-评分]列表if is_rec_list:return []# 推荐列表为空,按用户注册时选择的产品类别return get_select_tag_finance(user_id, finance_id)if is_rec_list:# 推荐列表不为空,且且is_rec_list: 值为True:返回推荐[用户-评分]列表return recommend_list# 过滤掉用户反馈过不喜欢的产品unlike_finance_ids = [d['finance_id'] for d inLikeRecommendfinance.objects.filter(user_id=user_id, is_like=0).values('finance_id')]# 过滤掉用户已评分的数据already_mark_ids = [d['finance_id'] for d in RateFinance.objects.filter(user_id=user_id).values('finance_id')]unrecommend = list(set(unlike_finance_ids + already_mark_ids))if finance_id and finance_id not in unrecommend:unrecommend.append(finance_id)finance_list = Finances.objects.filter(id__in=recommend_list).exclude(id__in=unrecommend).distinct().order_by("-like_num")return finance_listif __name__ == "__main__":main()# 加载模型进行预测for i in range(1, 7):print('************************', i, '**************************')embedding_main(i)
输出:
准确率是0.538,精准度是0.751,召回率是0.538,F1值是0.603


5、总结
我们可以看到,整个流程,深度学习框架Tensorflow帮我们做了大部分的工作,我们其实只是简单的提供了基础数据而已。
首先定义一个embedding (多维空间) 用来理解需要学习的原始数据 :
一个用户对象(含一个属性userId)
一个图书对象(含三个属性:bookId, userId, rating (用户评分))
这里需要进行学习的具体就是让机器理解那个“评分:rating”的含义)这里定义的embedding 维度为64, 本质就是让机器把评分rating 的值当作成一个64维度的空间来进行理解(其实就是从这个rating值当中提取出64个特征来重新定义这个rating)
随后对embedding 进行降维处理:
具体的操作与使用的降维函数曲线有关,这里采用的是先降为32维再降为1维的两道操作方式,原来的代表rating 的embedding 空间从64维降低到了1维。而此时的输出output 对象就是机器对rating完播向量所做出来的“自己的理解”。
最后通过对学习完的输出项output 进行mask(遮罩)测试,通过变换不同的mask(遮罩)来测试结果是否与原始数据相近,或一致,从而来证实机器学习的效果,也就是上文提到的反向传播方式的逆运算。
相关文章:
基于金融产品深度学习推荐算法详解【附源码】
深度学习算法说明 1、简介 神经网络协同过滤模型(NCF) 为了解决启发式推荐算法的问题,基于神经网络的协同过滤算法诞生了,神经网络的协同过滤算法可以 通过将用户和物品的特征向量作为输入,来预测用户对新物品的评分,从而解决…...
【Linux】centos配置可用的yum源
在 CentOS 系统中配置可用的 YUM 源(仓库)是保持系统更新和软件包管理的重要步骤。下面是一些步骤和示例,帮助你配置可用的 YUM 源: 1. 备份当前 YUM 仓库配置 首先,备份你当前的 YUM 仓库配置文件,以防万…...
LVS + Keepalived 高可用集群
一、LVSKeepalived 原理 1.1.LVS 负载均衡原理 LVS(Linux Virtual Server)是一种基于 Linux 内核的负载均衡技术,它通过 IPVS(IP Virtual Server)模块来实现。LVS 可以将客户端的请求分发到多个后端服务器上…...
PHP与数据库连接常见问题及解决办法
PHP与数据库连接常见问题及解决办法 在现代Web开发中,PHP与数据库的连接是不可或缺的一部分。无论是构建动态网站、内容管理系统(CMS)还是电子商务平台,PHP与数据库的交互都是核心功能之一。然而,在实际开发过程中&am…...
HarmonyOS-应用程序框架基础
应用程序框架与应用模型的区别 应用框架可以看做是应用模型的一种实现方式,开发人员可以用应用模型来描述应用程序的结构和行为的描述,然后使用应用程序框架来实现这些描述。 应用模型 应用模型是一个应用程序的模型,它是一种抽象的描述&a…...
使用 Doris 和 LakeSoul
作为一种全新的开放式的数据管理架构,湖仓一体(Data Lakehouse)融合了数据仓库的高性能、实时性以及数据湖的低成本、灵活性等优势,帮助用户更加便捷地满足各种数据处理分析的需求,在企业的大数据体系中已经得到越来越…...
【C语言】函数和数组实践与应用:开发简单的扫雷游戏
【C语言】函数和数组实践与应用:开发简单的扫雷游戏 1.扫雷游戏分析和设计1.1扫雷游戏的功能说明(游戏规则)1.2游戏的分析与设计1.2.1游戏的分析1.2.2 文件结构设计 2. 代码实现2.1 game.h文件2.2 game.c文件2.3 test.c文件 3. 游戏运行效果4…...
国内Mac,nimi安装homebrew完整过程
安装命令: 常规安装脚本: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 极速安装脚本: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.…...
C++基础——从C语言快速入门
目录 输入输出 标准输出流 ( cout ) 标准输入流 ( cin ) 标准错误流 ( cerr ) 和标准日志流 ( clog ) 编程示例 基本变量类型 宽字符的用法 climits 如何使用 编程示例 注意事项 流程控制 条件语句 循环语句 跳转语句 函数 函数的基本结构 编程示例 函数的组成…...
玩转python:通俗易懂掌握高级数据结构-collections模块之Counter
引言 Counter是Python中collections模块提供的一个强大工具,用于统计可哈希对象的出现次数。它非常适合用于频率统计、词频分析、数据聚合等场景。本文将详细介绍Counter的关键用法和特性,并通过8个丰富的案例帮助读者掌握其应用。 关键用法和特性表格 …...
Windows远程桌面黑屏怎么办?
在使用Windows远程桌面连接另一台电脑时,用户经常会遇到Windows远程桌面黑屏的问题。那么,该如何有效地解决Windows远程桌面黑屏的问题呢?遇到远程桌面连接黑屏的问题时,可以通过在本地组策略编辑器中禁用WDDM图形显示驱动来解决。…...
82.HarmonyOS NEXT 性能优化指南:从理论到实践
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! HarmonyOS NEXT 性能优化指南:从理论到实践 文章目录 HarmonyOS NEXT 性能优化指南:从理论到实践1. 性能优化概述1.1 性能指…...
python笔记2
变量:含义 一个容器,计算机当中的存储空间。 可以理解为一个用于标识或引用数据的名字或标签。 作用: 可以通过定义一个变量来给需要使用多次的数据命名,就像一个标签一样。下次需要使用这个数据时,只需要通过这个变…...
深度学习 Deep Learning 第1章 深度学习简介
第1章 深度学习简介 概述 本章介绍人工智能(AI)和深度学习领域,讨论其历史发展、关键概念和应用。解释深度学习如何从早期的AI和机器学习方法演变而来,以及如何有效解决之前方法无法应对的挑战。 关键概念 1. 人工智能的演变 …...
Nest系列:NestJS 中 Logger 完全指南:从基础到企业级实践-04
一、Logger 的核心价值 在服务端应用中,日志系统承担着三大核心职责: 系统监控:实时反馈应用健康状态问题追踪:快速定位异常根源行为审计:记录关键业务操作NestJS 内置的日志系统提供了开箱即用的解决方案,支持: ✅ 多日志级别管理 ✅ 上下文感知日志 ✅ 自定义输出格式…...
机器学习 [白板推导](二)[线性回归]
3. 线性回归 3.1. 问题定义 假设两个变量 x ⃗ \vec{x} x 和 y y y 之间存在线性关系(例如 y w ⃗ T x ⃗ b y\vec{w}^T\vec{x}b yw Tx b),如何利用数据 D a t a : { ( x ⃗ i , y i ) } i 1 N Data:\{(\vec{x}_i,y_i)\}_{i1}^N Data…...
解决Windows版Redis无法远程连接的问题
🌟 解决Windows版Redis无法远程连接的问题 在Windows系统下使用Redis时,很多用户会遇到无法远程连接的问题。尤其是在配置了Redis并尝试通过工具如RedisDesktopManager连接时,可能会报错“Cannot connect to ‘redisconnection’”。今天&am…...
麒麟服务器操作系统Sqlite部署手册
软件简介 SQLite****介绍 SQLite是一个进程内的轻量级嵌入式数据库,它的数据库就是一个文件,实现了自给自足、无服务器、零配置的、事务性的SQL数据库引擎。它是一个零配置的数据库,这就体现出来SQLite与其他数据库的最大的区别:SQLite不需要在系统中配置,直接可以使用。…...
Qt C++ 常用压缩库推荐 快速压缩 解压缩数据
在Qt C中,如果你需要快速压缩和解压缩数据,可以使用以下几种库: 1. zlib 简介: zlib 是一个非常流行的压缩库,支持 DEFLATE 压缩算法。它被广泛用于各种应用程序中,包括Qt。 集成: Qt 本身已经集成了 zlib࿰…...
架构师面试(十五):熔断设计
问题 某电商平台经常需要在大促运营活动中暂停评论、退款等业务,基于服务治理的设计理念,我们需要对该电商平台微服务系统的【服务熔断】进行设计,对此下面描述中说法正确的有哪几项呢? A. 服务管控系统管理着平台中所有服务之间…...
解析GNGGA数据,C语言单片机
GPS模块的一帧数据是: $GNGGA,130333.000,4143.43651,N,12328.96485,E,1,14,1.2,93.1,M,0.0,M,,*45 $GNGLL,4143.43651,N,12328.96485,E,130333.000,A,A*4D $GPGSA,A,3,05,07,11,13,20,29,30,195,,,,,2.3,1.2,2.0*05 $BDGSA,A,3,08,13,28,33,38,42,,,,,,,2.3,1.2,2.0*2E $GPG…...
Navicat如何查看密码
近期遇到需要将大部分已存储的navicat数据库转发给其他人,于是乎进行导出文件 奈何对方不用navicat,无法进行文件的导入从而导入链接 搜罗navicat的密码查看,大部分都为php代码解析 以下转载GitHub上看到的一个python代码解析的脚本 这里是对…...
力扣143重排链表
143. 重排链表 给定一个单链表 L 的头节点 head ,单链表 L 表示为: L0 → L1 → … → Ln - 1 → Ln 请将其重新排列后变为: L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 不能只是单纯的改变节点内部的值,而是需要实际的…...
【GPT入门】第24课 langfuse介绍
【GPT入门】第24课 langfuse介绍 1. langfuse概念与作用2. 代码3. 页面效果4. 设计模式1. 装饰器模式2. 上下文管理模式1. langfuse概念与作用 Langfuse是一款专为大规模语言模型(LLM)应用开发设计的开源平台。其作用主要包括以下几个方面: 提升开发效率:通过消除LLM应用构…...
HarmonyOS NEXT个人开发经验总结
文章目录 1. 开发环境配置1.1 工具链安装流程1.2 环境配置代码 2. 项目架构设计2.1 分层架构图2.2 模块化配置 3. 核心开发实践3.1 声明式UI开发3.2 分布式数据管理 4. 性能优化策略4.1 性能优化流程图4.2 优化实践代码 5. 安全与权限管理5.1 权限申请流程5.2 安全存储示例 6. …...
Python基于深度学习的多模态人脸情绪识别研究与实现
一、系统架构设计 A[数据采集] --> B[预处理模块] B --> C[特征提取] C --> D[多模态融合] D --> E[情绪分类] E --> F[系统部署] F --> G[用户界面] 二、数据准备与处理 1. 数据收集 - 视频数据:FER2013(静态图像࿰…...
golang快速上手基础语法
变量 第一种,指定变量类型,声明后若不赋值,使用默认值0 package mainimport "fmt"func main() {var a int //第一种,指定变量类型,声明后若不赋值,使用默认值0。fmt.Printf(" a %d\n"…...
【MySQL】多表操作 —— 外键约束
目录 多表关系一对一关系一对多/多对一关系多对多关系 外键约束基本概念一对多/多对一创建外键约束外键约束下的数据操作数据插入数据删除 删除外键约束 多对多创建外键约束外键约束下的数据操作数据插入数据删除 删除外键约束 多表关系 MySQL 多表之间的关系可以概括为&#…...
⭐算法OJ⭐两数之和【哈希表】(C++ 实现)Two Sum
“两数之和”(Two Sum)是一道非常经典的算法题目,几乎是算法入门和面试准备的必做题之一。它的经典性体现在以下几个方面: 1. 算法入门的基础题目 这道题目是许多初学者接触 哈希表(Hash Table) 或 字典&…...
从被动响应到主动预见:智能可观测性技术的变革与实践
思维导图 一、引言 🌃 想象一下,在一个深夜 🌙,你的关键业务系统突然出现故障 🚨。传统情况下,你可能会收到大量不相关的告警 📱💬💬💬,然后花费数小时甚至数天时间 ⏳,在错综复杂的系统架构中寻找根本原因 🔍。而在智能可观测性的世界里,故障发生前系统…...
