医学数据分析实训 项目十 基于深度残差神经网络的皮肤癌检测

文章目录

    • 综合实践三 基于深度残差神经网络的皮肤癌检测
      • 实现步骤1:图像数据预处理
      • 实现步骤2:模型构建
      • 实现步骤3:性能度量
      • 提交要求
    • 1 基于深度残差神经网络的皮肤癌检测代码
    • 2 结果分析

综合实践三 基于深度残差神经网络的皮肤癌检测

皮肤镜图像是检查皮肤癌黑色素瘤的主要手段。本实践项目通过构建深度残差神经网络提取皮肤镜图像的高维特征,使用残差学习防止网络梯度退化,降低网络训练的难度,实现黑色素瘤的有效识别。

实践项目所使用的数据集由多名患者的皮肤癌组织纤维图像组成,分为训练集和预测集,每部分包含良性(benign,标签定义为1)和恶性(malignant,标签定义为0)两种。

请将皮肤癌组织显微图像进行预处理,并在处理后的数据集基础上,运用基于深度残差神经网络模型对训练集进行训练,并对测试集进行预测。

实现步骤1:图像数据预处理

  1. 安装 Pillownumpyscikit-learnkerastensorflowmatplotlib 库;
  2. 对图像数据进行归一化和格式转换。将“jpg”图像传输到数组 IMG,并将所有数据转换成矩阵形式;
  3. 定义标签,良性定义标签为 1,恶性定义标签为 0;
  4. 分别合并训练集和测试集中的良性肿瘤数据和恶性肿瘤数据;

实现步骤2:模型构建

  1. 使用 Keras 库中的 ImageDataGenerator() 函数进行数据增强;
  2. 读取预处理后的图像,划分训练集和测试集;
  3. 使用 Sequential() 建立模型,并进行模型训练;
  4. 使用测试数据对模型进行测试;
  5. 对模型进行评估;

实现步骤3:性能度量

  1. 绘制模型精度折线图,查看训练效果;
  2. 输出显示恶性的预测结果前 8 个图像;
  3. 输出显示良性的预测结果前 8 个图像;

提交要求

  1. 提交实现本实践任务的所有代码(可执行,非.doc、.txt 等文本格式);
  2. 提交综合实践任务书(word 格式),包括小组成员分工、分析目的、数据预处理、算法介绍、结果分析等内容;
  3. 提交“四、性能度量”中 2 和 3 输出的图像;

1 基于深度残差神经网络的皮肤癌检测代码

在虚拟环境下进行该任务--基于深度残差神经网络的皮肤癌检测
anaconda下的虚拟环境,python版本是3.10
我的虚拟环境路径: D:\envs\miniconda\envs\cancer_detectionconda create -n cancer_detection python=3.10conda activate cancer_detectionconda deactivate安装要使用的包pip install Pillow numpy scikit-learn keras tensorflow matplotlib
import timefrom keras.src.layers import Conv2D, MaxPooling2D, Flatten, Dense
from keras import Sequential, Input
import os
from PIL import Image
import numpy as np
from sklearn.model_selection import train_test_split
from keras.src.optimizers import Adam
from keras.src.legacy.preprocessing.image import ImageDataGenerator
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix
import matplotlib.pyplot as plt
# 显示中文
plt.rcParams['font.sans-serif'] = ['SimHei']
# 显示负号
plt.rcParams['axes.unicode_minus'] = False
# 从指定的文件夹中加载图像
def load_images_from_folder(folder, class_name):jpg_path = os.path.join(folder, class_name)  #data/train/benignimages = []# 添加计数器count = 0  #遍历指定路径下的所有文件名for filename in os.listdir(jpg_path): img = Image.open(os.path.join(jpg_path, filename))  #224*224if img is not None:img = np.array(img) / 255.0  # 归一化,将图像像素值归一化到0-1images.append(img)count += 1  # 更新计数器return images, count# 训练集文件夹路径 测试集文件夹路径
train_folder = "data/train"
test_folder = "data/test"
# 第一个类别名称 # 第二个类别名称
class1_name = "benign"
class2_name = "malignant"train_class1_images, train_class1_count = load_images_from_folder(train_folder, class1_name)
train_class2_images, train_class2_count = load_images_from_folder(train_folder, class2_name)
test_class1_images, test_class1_count = load_images_from_folder(test_folder, class1_name)
test_class2_images, test_class2_count = load_images_from_folder(test_folder, class2_name)print("类别 {} 的训练集图像数目: {}".format(class1_name, train_class1_count))
print("类别 {} 的训练集图像数目: {}".format(class2_name, train_class2_count))
print("类别 {} 的测试集图像数目: {}".format(class1_name, test_class1_count))
print("类别 {} 的测试集图像数目: {}".format(class2_name, test_class2_count))

类别 benign 的训练集图像数目: 1440
类别 malignant 的训练集图像数目: 1197
类别 benign 的测试集图像数目: 360
类别 malignant 的测试集图像数目: 300

# 定义标签
train_class1_labels = np.ones(len(train_class1_images))
train_class2_labels = np.zeros(len(train_class2_images))
test_class1_labels = np.ones(len(test_class1_images))
test_class2_labels = np.zeros(len(test_class2_images))# 合并训练集和测试集的图片和标签
benign_images = np.concatenate((train_class1_images, test_class1_images))  #训练集和验证集中的良性图片
benign_labels = np.concatenate((train_class1_labels, test_class1_labels))
malignant_images = np.concatenate((train_class2_images, test_class2_images))   #训练集和验证集中的恶性图片
malignant_labels = np.concatenate((train_class2_labels, test_class2_labels))
#查看合并后的图像数量
total_benign_images = benign_images.shape[0]
total_malignant_images = malignant_images.shape[0]
print("合并后的良性图片数量:", total_benign_images)
print("合并后的恶性图片数量:", total_malignant_images)
print("benign_labels的数量:", benign_labels.shape[0])
print("malignant_labels的数量:", malignant_labels.shape[0])

合并后的良性图片数量: 1800
合并后的恶性图片数量: 1497
benign_labels的数量: 1800
malignant_labels的数量: 1497

# 划分训练集和测试集
X = np.concatenate((benign_images, malignant_images))
y = np.concatenate((benign_labels, malignant_labels))
# 输出X的数量
print("X的数量:", X.shape[0])
# 输出y的数据量
print("y的数据量:", y.shape[0])X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

X的数量: 3297
y的数据量: 3297


# 开始计时
start_time = time.time()#简单的卷积神经网络(CNN)模型
input_shape = (224, 224, 3)
model = Sequential()
model.add(Input(shape=input_shape))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dense(10, activation='softmax'))
input_data = np.random.rand(1, 224, 224, 3)
output = model(input_data)# 编译模型,Adam优化器的默认学习率通常是0.001
model.compile(optimizer=Adam(), loss='sparse_categorical_crossentropy', metrics=['accuracy'])#使用Adam优化器、稀疏类别交叉熵损失函数和准确率评估指标来编译模型
# 定义数据增强操作
datagen = ImageDataGenerator(rotation_range=20,       # 随机旋转角度范围(0~20度)width_shift_range=0.1,   # 水平平移范围(相对于总宽度的比例)height_shift_range=0.1,  # 垂直平移范围(相对于总高度的比例)horizontal_flip=True,    # 随机水平翻转
)# 使用数据增强生成器对训练数据进行增强,并设置批量大小为32
train_generator = datagen.flow(X_train, y_train, batch_size=32) #32# 使用增强后的数据训练模型,共进行10个周期的训练
history = model.fit(train_generator, epochs=10)# # 使用测试数据对模型进行测试
y_pred = model.predict(X_test)
#每一行代表一个样本的预测概率分布,沿着每一行(即每个样本)寻找最大值的索引
y_pred_classes = np.argmax(y_pred, axis=1)# 结束计时
end_time = time.time()# 计算和输出所花费的时间
elapsed_time = end_time - start_time
print(f"进程完成所需时间: {elapsed_time:.2f} 秒")

83/83 ━━━━━━━━━━━━━━━━━━━━ 39s 421ms/step - accuracy: 0.5926 - loss: 12.5544
Epoch 2/10
83/83 ━━━━━━━━━━━━━━━━━━━━ 34s 383ms/step - accuracy: 0.7577 - loss: 0.4838
Epoch 3/10
83/83 ━━━━━━━━━━━━━━━━━━━━ 33s 383ms/step - accuracy: 0.7646 - loss: 0.4563
Epoch 4/10
83/83 ━━━━━━━━━━━━━━━━━━━━ 32s 364ms/step - accuracy: 0.7697 - loss: 0.4524
Epoch 5/10
83/83 ━━━━━━━━━━━━━━━━━━━━ 32s 369ms/step - accuracy: 0.7690 - loss: 0.4457
Epoch 6/10
83/83 ━━━━━━━━━━━━━━━━━━━━ 32s 374ms/step - accuracy: 0.7890 - loss: 0.4195
Epoch 7/10
83/83 ━━━━━━━━━━━━━━━━━━━━ 32s 368ms/step - accuracy: 0.7764 - loss: 0.4321
Epoch 8/10
83/83 ━━━━━━━━━━━━━━━━━━━━ 32s 369ms/step - accuracy: 0.7921 - loss: 0.4323
Epoch 9/10
83/83 ━━━━━━━━━━━━━━━━━━━━ 37s 428ms/step - accuracy: 0.7821 - loss: 0.4326
Epoch 10/10
83/83 ━━━━━━━━━━━━━━━━━━━━ 34s 391ms/step - accuracy: 0.7929 - loss: 0.4186
21/21 ━━━━━━━━━━━━━━━━━━━━ 1s 49ms/step
进程完成所需时间: 349.87 秒

# 计算评估指标
accuracy = accuracy_score(y_test, y_pred_classes)
precision = precision_score(y_test, y_pred_classes, average='weighted') #计算加权平均值
recall = recall_score(y_test, y_pred_classes, average='weighted')
f1 = f1_score(y_test, y_pred_classes, average='weighted')
confusion = confusion_matrix(y_test, y_pred_classes)print('Accuracy:', accuracy)
print('Precision:', precision)
print('Recall:', recall)
print('F1 Score:', f1)
print('Confusion Matrix:', confusion)
# 保存数据
if not os.path.exists('./结果分析'):os.makedirs('./结果分析')
with open('./结果分析/计算评估指标.txt', 'a') as f:f.write('计算评估指标\n')f.write(f'Accuracy: {accuracy}\n')f.write(f'Precision: {precision}\n')f.write(f'Recall: {recall}\n')f.write(f'F1 Score: {f1}\n')f.write(f'Confusion Matrix: {confusion}\n')

Accuracy: 0.8106060606060606
Precision: 0.8103019434437978
Recall: 0.8106060606060606
F1 Score: 0.8094419197353939
Confusion Matrix: [[211 74]
[ 51 324]]

# 提取训练精度和验证精度数据
train_accuracy = history.history['accuracy']
loss = history.history['loss']
# 绘制精度折线图
plt.plot(train_accuracy, label='Training Accuracy')
plt.plot(loss, label='loss')
plt.title('Model Accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.ylim(0, 1)
plt.legend()
plt.savefig('./结果分析/Model Accuracy.png')
plt.show()

在这里插入图片描述

# 预测结果数组 y_pred_classes 中找出所有预测为恶性(值为0)的索引,然后取前8个索引。
malignant_pred_indices = np.where(y_pred_classes == 0)[0][:8]
# 使用这些索引从测试数据集 X_test 中提取对应的图像数据
malignant_pred_images = X_test[malignant_pred_indices]
# 在一个2x4的子图网格中显示恶性预测图像。
for i, image in enumerate(malignant_pred_images):  # 遍历恶性预测图像列表,同时获取每个图像及其索引。plt.subplot(2, 4, i + 1)  #创建一个2行4列的子图网格,并将当前图像放置在子图中plt.imshow(image.squeeze(), cmap='gray')   #灰度颜色映射显示图像,移除单维度条目,确保图像数据的形状正确plt.axis('off')plt.title(f'Malignant {i + 1}')  #为当前子图设置标题plt.savefig('./结果分析/恶性预测结果.png') 
plt.show()

在这里插入图片描述

# 获取良性预测结果前8个图像的索引
benign_pred_indices = np.where(y_pred_classes == 1)[0][:8]
# 获取良性预测结果前8个图像
benign_pred_images = X_test[benign_pred_indices]
# 显示良性预测结果前8个图像
for i, image in enumerate(benign_pred_images):plt.subplot(2, 4, i + 1)plt.imshow(image.squeeze(), cmap='gray')plt.axis('off')plt.title(f'Benign {i + 1}')
plt.savefig('./结果分析/良性预测结果.png')
plt.show()

在这里插入图片描述

2 结果分析

1.任务分工

2.分析目的
通过构建神经网络提取皮肤镜图像的高维特征,实现黑色素瘤的有效识别。

3.数据预处理
(1)格式转换
使用np.array(img),将“jpg” 图像传输到阵列 IMG,并将所有数据转换成矩阵形式

(2)对图像数据进行归一化
使用np.array(img) / 255.0,将每个像素值除以255.0,可以将像素值缩放到0到1之间的范围,实现归一化

(3)定义标签, 良性定义标签为 1, 恶性定义标签为 0;
train_class1_labels = np.ones(len(train_class1_images))
创建一个长度为与良性类别图像数目等同的数组,数组中的所有元素都为1。这表示良性肿瘤数据中的所有图像都属于类别1,良性定义标签为 1;
train_class2_labels = np.zeros(len(train_class2_images))
创建一个长度为与恶性类别图像数目等同的数组,数组中的所有元素都为0。这表示恶性肿瘤数据中的所有图像都属于类别0,恶性定义标签为 0。

(4)分别合并训练集和测试集中的良性肿瘤数据和恶性肿瘤数据

benign_images = np.concatenate((train_class1_images, test_class1_images))
benign_labels = np.concatenate((train_class1_labels, test_class1_labels))

将原数据集中分别属于训练集和测试集的同类别数据进行组合,即两个数组按照它们的第一个维度(通常是行)进行拼接,得到完整的良性肿瘤数据集和恶性肿瘤数据集,其对应标签同样方式进行组合,保证图片与标签的类别对应关系。
4.算法介绍
建立一个简单的卷积神经网络模型,其中包括:

  • 输入层:input_shape = (224, 224, 3)定义了输入图像的形状,其中224x224是图像的宽度和高度,3是图像的通道数(通常对应于RGB三个颜色通道)。
  • 模型构建:使用Sequential()创建了一个序列化的模型,然后通过.add()方法依次添加各个层。
  • Conv2D(32, (3, 3), activation=‘relu’):添加了一个卷积层,有32个过滤器,每个过滤器的大小为3x3,激活函数为ReLU。
  • MaxPooling2D((2, 2)):添加了一个最大池化层,池化窗口大小为2x2。
  • Flatten():将多维的卷积层输出展平为一维,以便连接到全连接层。
  • Dense (64, activation=‘relu’):添加了一个全连接层,有64个神经元,激活函数为ReLU。
  • Dense(2, activation=‘softmax’):添加了另一个全连接层,作为输出层,有2个神经元(对应于2个类别),激活函数为softmax,用于多分类任务。

5.结果分析
(1)模型精度折线图
见上图

模型采用Adam优化器,sparse_categorical_crossentropy损失函数,训练10轮,根据图像可以看出模型损失函数逐渐下降,准确率逐渐上升。

(2)评价指标结果

  • 准确率(Accuracy):0.8257575757575758,表示模型预测正确的样本占总样本的比例为82.58%。这是一个相对较高的准确率,说明模型在大多数情况下能够正确预测。
  • 精确率(Precision):0.8256871986269648,表示模型预测为正例的样本中真正为正例的比例为82.57%。精确率关注的是模型预测为正例的准确性,较高的精确率意味着模型预测出的正例中错误的可能性较低。
  • 召回率(Recall):0.8257575757575758,表示实际为正例的样本中被模型正确预测为正例的比例为82.58%。召回率关注的是模型能够找出所有正例的能力,较高的召回率意味着模型能够识别出更多的真实正例。
  • F1 Score:0.8257204698469889,F1 Score是精确率和召回率的调和平均值,用于综合评价模型的性能。较高的F1 Score意味着模型在精确率和召回率之间取得了较好的平衡

(3)混淆矩阵
Confusion Matrix: [[256 29]
[ 87 289]]
含义如下:

  • 第一行第一列(256):表示实际为正类且被模型正确预测为正类的数量。
  • 第一行第二列(29):表示实际为正类但被模型错误预测为负类的数量(即假阴性,Type I错误)。
  • 第二行第一列(87):表示实际为负类但被模型错误预测为正类的数量(即假阳性,Type II错误)。
  • 第二行第二列(289):表示实际为负类且被模型正确预测为负类的数量。

每次运行会有小差异

计算评估指标
Accuracy: 0.8257575757575758
Precision: 0.8395988183724034
Recall: 0.8257575757575758
F1 Score: 0.8265118719664174
Confusion Matrix: [[256  29][ 86 289]]
计算评估指标
Accuracy: 0.8106060606060606
Precision: 0.8103019434437978
Recall: 0.8106060606060606
F1 Score: 0.8094419197353939
Confusion Matrix: [[211  74][ 51 324]]

(4)输出显示恶性的预测结果前 8 个图像
见上文

(5)输出显示良性的预测结果前 8 个图像
见上文

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

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

相关文章

毕业设计选题:基于ssm+vue+uniapp的校园商铺系统小程序

开发语言:Java框架:ssmuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:M…

828华为云征文 | 在华为云X实例上部署微服务架构的文物大数据管理平台的实践

前言 文物大数据管理平台的需求日益增长,要求系统具备强大的数据存储、智能查询和数据分析功能。通过微服务架构,平台可以灵活地管理用户、文件存储、文物知识、资源管理以及报表统计等模块。本文将以实际案例为基础,详细介绍如何在华为云Fl…

实现西门子PLC与发那科机器人通讯接收正负值偏移

PLC与发那科机器人通讯组信号的无法接受负数,并且高低字节取反; 解决办法如下: 在发送数据时双方约定一个基数,通讯时双方上这个值,或减去这个值即可; 如下图,当前约定收发数据范围为-20到20之…

【2024】前端学习笔记8-内外边距-边框-背景

学习笔记 外边距:Margin内边距:Padding边框:Border背景:Background 外边距:Margin 用于控制元素周围的空间,它在元素边框之外创建空白区域,可用于调整元素与相邻元素(包括父元素和兄…

ORCA-3D避障代码和原理解析

二维ORCA原理参考: https://zhuanlan.zhihu.com/p/669426124 ORCA原理图解代码解释 1. 找到避障速度增量 u 碰撞处理分为三种情况: (1)没有发生碰撞,且相对速度落在小圆里 (2)没有发生碰撞&a…

蓝星多面体foc旋钮键盘复刻问题详解

介绍&#xff1a; 本教程是针对立创开源项目 承载我所有幻想的键盘 - 立创开源硬件平台 作者是 蓝星多面体 这里我总结一下我复刻过程中的一些问题 一 <<编译环境怎么搭建&#xff1f;>> 第一步 安装vscode 下载vscode &#xff08;可以在各大应用平台…

如何删除EXCELL文件中的空行?

1&#xff0c;选择某一列 2&#xff0c;点击《开始》《查找和选择》>《定位条件》&#xff0c;调出《定位条件》的选择框&#xff1b; 3&#xff0c;在定位条件选项框&#xff0c;选择《空值》&#xff1b; 4&#xff0c;找到变灰被选中的某一行&#xff0c;右击《删除》 5&…

高级算法设计与分析 学习笔记6 B树

B树定义 一个块里面存了1000个数和1001个指针&#xff0c;指针指向的那个块里面的数据大小介于指针旁边的两个数之间 标准定义&#xff1a; B树上的操作 查找B树 创建B树 分割节点 都是选择正中间的那个&#xff0c;以免一直分裂。 插入数字 在插入的路上就会检查节点需不需要…

Qt 类型选择器和类选择器的区别

概念上的区别请查看此篇博客&#xff1a;Qt 样式表、选择器、盒子模型&#xff0c;下面我直接举例说明。 示例界面&#xff1a; 1、类型选择器&#xff1a; QWidget {background-color: rgb(255, 85, 127); }运行结果&#xff08;因为QPushButton是QWidget的子类&#xff0…

MongoDB的备份和恢复命令

一、下载 MongoDB Database Tools 官方网址&#xff1a;Download MongoDB Command Line Database Tools | MongoDB 将解压后的文件夹移动到MongoDB的bin目录下&#xff0c;同时配置mongodb-database-tools的bin目录进入环境变量。 以上有问题请参考文章&#xff1a;使用cmd命…

已解决npm ERR! request to https://registry.npm.taobao.org/@vant%2farea-data failed

在npm insrall的时候&#xff0c;报错&#xff0c;完整报错如下 简单来说就是淘宝原镜像域名&#xff08;http://registry.npm.taobao.org&#xff09;的 HTTPS 证书到期了&#xff0c;导致npm在使用镜像的时候报错&#xff0c;需要更换镜像域名。 清空缓存 npm cache clean …

计算机毕业设计Python+Flask微博情感分析 微博舆情预测 微博爬虫 微博大数据 舆情分析系统 大数据毕业设计 NLP文本分类 机器学习 深度学习 AI

首先安装需要的python库&#xff0c; 安装完之后利用navicat导入数据库文件bili100.sql到mysql中&#xff0c; 再在pycharm编译器中连接mysql数据库&#xff0c;并在设置文件中将密码修改成你的数据库密码。最后运行app.py&#xff0c;打开链接&#xff0c;即可运行。 B站爬虫数…

pytorch学习笔记一:作用、安装和基本使用方法、自动求导机制、自制线性回归模型、常见tensor格式、hub模块介绍

文章目录 一、安装二、基本使用方法①创建一个矩阵②获得随机值③初始化全零矩阵④直接传入数据⑤构建矩阵&#xff0c;然后随机元素值⑥展示矩阵大小⑦矩阵计算8、取索引9、view操作&#xff1a;改变矩阵维度10、与numpy的协同操作 三、自动求导机制1&#xff09;定义tensor成…

介绍一下常用的激活函数?

常用的激活函数 Sigmoid函数Tanh函数ReLU函数Leaky ReLU函数Softmax函数 Sigmoid函数 特点&#xff1a; 将任意实数映射到(0,1)区间内&#xff0c;输出值可以作为概率来解释。 函数平滑且易于求导&#xff0c;但其导数在两端趋近于0&#xff0c;即存在梯度消失问题。 输出值不…

算法训练——day18 两数之和三数之和

1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素。 你可以按任意顺序返回…

【Java版】云HIS系统源码

云HIS系统介绍 云HIS系统是一款满足基层医疗机构各类业务需要的健康云产品。该产品能帮助基层医疗机构完成日常各类业务&#xff0c;提供病患挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查询、医生站和护士站等一系列常规功能&#xff0c;还能与公卫、PACS等各类…

【有啥问啥】深入解析:机器学习中的过拟合与欠拟合

深入解析&#xff1a;机器学习中的过拟合与欠拟合 在机器学习中&#xff0c;过拟合&#xff08;overfitting&#xff09;和欠拟合&#xff08;underfitting&#xff09;是模型性能中常见的两大挑战。它们反映了模型的学习能力与泛化能力的不平衡&#xff0c;直接影响模型在训练…

mac m1 electron生产环境使用prisma,sqlite

最近在用electron开发一个适合自己的小应用&#xff0c;技术选型中使用prisma和sqlite在进行数据存储&#xff0c;写这篇文章的目的就是用来记录下遇到的一些问题。 开发环境使用prisma 1、开发环境使用prisma非常的简单&#xff0c;只需要按照教程安装prisma&#xff0c;然后…

修复 blender 中文输入 BUG (linux/wayland/GNOME/ibus)

blender 是一个很好的 开源 3D 建模/动画/渲染 软件, 功能很强大, 跨平台 (GNU/Linux, Windows 等系统都支持). 然而, 窝突然发现, blender 居然不支持中文输入 (linux) ! 这怎么能忍 ? 再一查, 不得了, 这居然是个 3 年前一直未解决的陈年老 BUG. 不行, 这绝对忍不了, 这个 …

【Azure Redis 缓存】Azure Redis出现了超时问题后,记录一步一步的排查出异常的客户端连接和所执行命令的步骤

问题描述 Azure Redis在使用的过程中&#xff0c;多次无规律的出现超时问题。抓取到客户端的异常错误后&#xff0c;想进一步的分析是何原因导致了如下异常呢&#xff1f; Timeout awaiting response (outbound0KiB, inbound0KiB, 5984ms elapsed, timeout is 5000ms), command…