项目实战-基于信号处理与SVM机器学习的声音情感识别系统
目录
一.背景描述
二.理论部分
三.程序设计
编程思路
流程图
1.信号部分 创建数据 generate_samples.py
头文件
生成函数 generate_emotion_sample
传入参数
存储路径
生成参数
创建基础正弦波信号
调制基础正弦波
对于愤怒可以增加噪声
归一化信号
存储
主函数 main
2.交叉部分 特征提取 audio_emotion.py
头文件
提取单个文件的特征 extract_features_from_file
传入参数
提取特征向量
计算统计值并返回矩阵
提取各情感的特征 extract_features_from_directory
传入参数
初始化
提取文件 & 识别特征
训练情感识别模型 train_emotion_model
传入参数
划分训练集和测试集
训练SVM模型
评估测试集
计算混淆矩阵
返回
保存模型
加载模型
预测单个音频的情感
混淆矩阵可视化
音频特征可视化
传入参数
处理音频
特征提取
可视化并保存
返回
3.机器学习部分 train_model.py
为何要独立出一个训练脚本
头文件
主函数 main
4.封装部分 main.py
创建项目目录
提取特征并训练模型
预测单个文件情感
显示
主逻辑
5.预测部分 predict.py
头文件
可视化音频特征
主逻辑
应用
四.运行展示
初始化目录
生成样本
训练模型
查看结果并分析
应用模型
查看分析图
一.背景描述
智能识别不同情景下的声音信号体现的情感,比如客户接电话时的语音情感,还可以用于智能手表、人工智能助手(比如豆包的聊天过程中的人类情感反馈,提高豆包“情商”)等等
二.理论部分
1.首先分析了不同情感声音信号的特征,用于下面的构造信号
2.构造不同情感的声音信号(通过将时间序列代入基准正弦信号,接着进行加、乘操作进行调制)用于训练SVM模型
3.对信号进行时频域变换,比如傅立叶变换
chroma = librosa.feature.chroma_stft(y=y, sr=sr)
4.进行特征提取,捕捉谱质心、谱带宽、谱对比度等等
5.进行特征的统计,计算了四种统计量:均值、标准差、最小值、最大值
6.通过均方根计算能量,这是情感表达的重要指标
7.特征空间降维,通过统计的方式进行了隐式降维
三.程序设计
编程思路
整体框架是:
1.信号生成 generate_samples.py
2.特征提取 audio_emotion.py
3.训练模型 train_model.py
4.封装模块 main.py
5.应用模型 predict.py
流程图
1.信号部分 创建数据 generate_samples.py
头文件
import os
import numpy as np
import librosa
import soundfile as sf
from scipy.io import wavfile
生成函数 generate_emotion_sample
传入参数
emotion 情感
freq_range 生成音频信号的频率范围
duration_range 生成信号的持续时间范围
num_samples 生成的音频样本数量
存储路径
emotion_dir = os.path.join("dataset", emotion)os.makedirs(emotion_dir, exist_ok=True)
dataset 是数据集的根目录,在根目录下创建名为传入参数emotion的子目录
第二句的作用是保证文件夹存在
生成参数
首先我们得明确各情感声音特色
"happy"
:高频、短持续时间,模拟快乐情感。"sad"
:低频、长持续时间,模拟悲伤情感。"angry"
:中高频、短脉冲,模拟愤怒情感。"neutral"
:中等频率和持续时间,模拟中性情感。
那么我们只需要判断,然后分支为各情感创建独特的参数就好
以“happy”为例
首先我们要从指定的频率中随机选择频率值,对应下面的np.random.uniform(freq_range[0], freq_range[1])语句,里面的freq_range[ 0 ] 和 freq_range[1] 分别代表频率范围的上下限,我们会在主函数中提前定义
(注意:我们这里得用numpy的random,而不是python自带的random函数,因为np的支持数组高效操作)
然后我们还需要持续时间,和频率同理也是np.random.uniform
接着我们设置了音频信号的振幅频率(音量),快乐的声音为0.6中等偏高来模拟
最后我们设置振幅调制的频率,快乐的是8.0:快速的变化,模拟快乐的活泼
其他的感情和快乐同理
for i in range(num_samples):if emotion == "happy":# 高频和短持续时间freq = np.random.uniform(freq_range[0], freq_range[1])duration = np.random.uniform(duration_range[0], duration_range[1])amplitude = 0.6modulation_freq = 8.0elif emotion == "sad":# 低频和长持续时间freq = np.random.uniform(freq_range[0]/2, freq_range[1]/2)duration = np.random.uniform(duration_range[0]*1.5, duration_range[1]*1.5)amplitude = 0.4modulation_freq = 2.0elif emotion == "angry":# 中高频和短脉冲freq = np.random.uniform(freq_range[0]*1.2, freq_range[1]*1.2)duration = np.random.uniform(duration_range[0], duration_range[1])amplitude = 0.8modulation_freq = 12.0else: # neutral# 中等频率和持续时间freq = np.random.uniform(freq_range[0]*0.8, freq_range[1]*0.8)duration = np.random.uniform(duration_range[0]*1.2, duration_range[1]*1.2)amplitude = 0.5modulation_freq = 4.0
创建基础正弦波信号
sample_rate = 22050t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)signal = amplitude * np.sin(2 * np.pi * freq * t)
首先我们设置了音频信号的采样频率,单位是“样本/秒”
然后我们用 numpy 的 linspace 创建了一个时间序列,用于表示信号的时间轴,第一个参数0表示时间序列起点,duration是时间序列的终点(也就是我们在上面生成的持续时间),第三个参数是时间序列的点数(计算方式:采样率乘以持续时间),endpoint保证时间序列不包含终点
然后我们生成一个正弦波信号,amplitude表示正弦波的振幅(音量),freq时频率(音调),t是上面生成的时间序列,通过 2 * np.pi * freq * t 将频率转为角频率,计算正弦波的相位
调制基础正弦波
我们还需要根据我们的情感对基础波进行处理
modulation = 1.0 + 0.3 * np.sin(2 * np.pi * modulation_freq * t)signal = signal * modulation
modulation是生成的调制信号,用于改变原始信号的振幅,其中 1.0 是基础振幅(乘法的初元), 0.3表示调制强度(影响程度)
第二句代码也就是将调制信号作用在原正弦波signal上
对于愤怒可以增加噪声
对于“angry”:加上信号
if emotion == "angry":noise = np.random.normal(0, 0.1, signal.shape)signal = signal + noise
归一化信号
进行归一化:除以max乘以1
限制信号在 [ -1,1 ] 中,确保生成的音频信号符合音频文件格式的要求,防止信号溢出
signal = signal / np.max(np.abs(signal))
存储
file_path = os.path.join(emotion_dir, f"{emotion}_sample_{i+1}.wav")sf.write(file_path, signal, sample_rate)print(f"生成样本: {file_path}")
emotion_dir 在函数刚进来一开始就定义了
然后我加了一句print方便调试看报错
主函数 main
def main():freq_range = (220, 880)duration_range = (2.0, 4.0)emotions = ["happy", "sad", "angry", "neutral"]for emotion in emotions:generate_emotion_sample(emotion, freq_range, duration_range, num_samples=50)print("所有测试样本生成完成!")if __name__ == "__main__":main()
freq_range 是频率范围
duration_range 是持续时间
num是生成数据集的个数,我先设置为50(多多益善)
然后用 for 遍历感情
2.交叉部分 特征提取 audio_emotion.py
头文件
import os
import numpy as np
import librosa
import librosa.display
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import classification_report, confusion_matrix
import joblib
import glob
提取单个文件的特征 extract_features_from_file
传入参数
file_path 文件的路径
win 计算特征的时间窗口长度
step 步长
提取特征向量
先读取音频文件
y, sr = librosa.load(file_path, sr=None)
读取MFCC特征
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
提取色度特征
chroma = librosa.feature.chroma_stft(y=y, sr=sr)
提取梅尔频谱
mel = librosa.feature.melspectrogram(y=y, sr=sr)
提取谱质心
spectral_centroid = librosa.feature.spectral_centroid(y=y, sr=sr)
提取谱带宽
spectral_bandwidth = librosa.feature.spectral_bandwidth(y=y, sr=sr)
提取谱对比度
spectral_contrast = librosa.feature.spectral_contrast(y=y, sr=sr)
提取谱平坦度
spectral_flatness = librosa.feature.spectral_flatness(y=y)
提取零交叉率
zcr = librosa.feature.zero_crossing_rate(y)
提取能量
energy = np.mean(librosa.feature.rms(y=y))
计算统计值并返回矩阵
features.append(energy)feature_names = []for name in ['mfccs', 'chroma', 'mel', 'spectral_centroid', 'spectral_bandwidth', 'spectral_contrast', 'spectral_flatness', 'zcr']:for stat in ['mean', 'std', 'min', 'max']:feature_names.append(f"{name}_{stat}")feature_names.append('energy')return np.array(features), feature_names
提取各情感的特征 extract_features_from_directory
传入参数
directory 数据集根目录
emotions 情感类别
初始化
features = []labels = []feature_names = None
其中
feature 特征向量
labels 情感标签
feature_names 特征的名称列表
提取文件 & 识别特征
首先我加了一句 print 方便调试
print(f"开始从以下类别提取特征: {emotions}")for emotion in emotions:emotion_dir = os.path.join(directory, emotion)if not os.path.isdir(emotion_dir):continuefor file_name in glob.glob(os.path.join(emotion_dir, "*.wav")):print(f"处理文件: {file_name}")feature_vector, names = extract_features_from_file(file_name)if feature_vector is not None:features.append(feature_vector)labels.append(emotion)if feature_names is None:feature_names = names
然后我们开始
遍历情感类别 for emotion in emotions(如果子目录不存在那就continue跳过)
遍历音频文件 for file_name in glob.glob(os.path.join(emotion_dir, "*.wav"))
提取音频特征 对于提取到的单个文件开始调用extract_features_from_file
存储特征和标签 append
最后我们返回
return np.array(features), np.array(labels), feature_names
后面的就是机器学习部分
训练情感识别模型 train_emotion_model
传入参数
feature 特征矩阵,每一行都是一个音频的特征向量,包含提取到的各种统计特征
labels 标签数组
test_size 测试集的比例,一般正常训练都是占比20%到30%,本次项目中设为0.2
划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=test_size, random_state=42)
训练SVM模型
model = SVC(kernel='rbf', probability=True)model.fit(X_train, y_train)
评估测试集
y_pred = model.predict(X_test)report = classification_report(y_test, y_pred, output_dict=True)
计算混淆矩阵
cm = confusion_matrix(y_test, y_pred)
返回
model SVM模型
report 分类报告
cm 混淆矩阵
X_test 测试集的特征矩阵,来评估模型性能
y_test 测试集的真实标签,用于对比
y_pred 模型在测试集的预测标签,用于对比
return model, report, cm, X_test, y_test, y_pred
保存模型
def save_model(model, output_path="emotion_model.pkl"):joblib.dump(model, output_path)print(f"模型已保存到 {output_path}")
加载模型
def load_model(model_path="emotion_model.pkl"):return joblib.load(model_path)
预测单个音频的情感
调用extract_features_from_file函数从指定file_path里面提取特征向量,然后特征预处理,将特征向量转换为模型可以接受的二维数组形状,接着调用model模型进行情感预测,返回每个情感类别的预测概率,便于分析模型的信心程度。这个函数在audio脚本中并没有被使用,而是在后面的main.py文件中被调用了
def predict_emotion(model, file_path):features, _ = extract_features_from_file(file_path)if features is not None:features = features.reshape(1, -1)prediction = model.predict(features)[0]probabilities = model.predict_proba(features)[0]return prediction, probabilitiesreturn None, None
混淆矩阵可视化
为了方便查看混淆矩阵,我用matplotlib来进行数据的可视化(由于我之前在数模比赛中做过斯皮尔曼相关矩阵的可视化,所以还是感觉轻车熟路的)
def visualize_confusion_matrix(cm, classes):plt.figure(figsize=(10, 8))plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)plt.title('混淆矩阵')plt.colorbar()tick_marks = np.arange(len(classes))plt.xticks(tick_marks, classes, rotation=45)plt.yticks(tick_marks, classes)thresh = cm.max() / 2.for i in range(cm.shape[0]):for j in range(cm.shape[1]):plt.text(j, i, format(cm[i, j], 'd'),horizontalalignment="center",color="white" if cm[i, j] > thresh else "black")plt.ylabel('真实标签')plt.xlabel('预测标签')plt.tight_layout()plt.savefig('confusion_matrix.png')plt.show()
效果展示
从图中可以直观的看到我们的模型准确率是不错的,具体的结论在后面分析
音频特征可视化
传入参数
audio_file 待分析的音频文件路径
处理音频
音频加载
y, sr = librosa.load(audio_file, sr=None)
音频持续时间计算
duration = librosa.get_duration(y=y, sr=sr)
特征提取
梅尔频谱
mel_spec = librosa.feature.melspectrogram(y=y, sr=sr)
mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)
MFCC(梅尔频谱倒谱系数)
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
色度图
chroma = librosa.feature.chroma_stft(y=y, sr=sr)
可视化并保存
plt.figure(figsize=(12, 10))# 波形plt.subplot(4, 1, 1)librosa.display.waveshow(y, sr=sr)plt.title('音频波形')# 梅尔频谱plt.subplot(4, 1, 2)librosa.display.specshow(mel_spec_db, sr=sr, x_axis='time', y_axis='mel')plt.colorbar(format='%+2.0f dB')plt.title('梅尔频谱')# MFCCplt.subplot(4, 1, 3)librosa.display.specshow(mfccs, sr=sr, x_axis='time')plt.colorbar()plt.title('MFCC')# 色度图plt.subplot(4, 1, 4)librosa.display.specshow(chroma, sr=sr, x_axis='time', y_axis='chroma')plt.colorbar()plt.title('色度图')plt.tight_layout()plt.savefig('audio_analysis.png')plt.show()
效果展现
返回
将特征数据和原始数据返回,便于后面分析
return mel_spec, mfccs, chroma, sr, y
3.机器学习部分 train_model.py
为何要独立出一个训练脚本
可以看到我们之前在audio_emotion.py中包含了一系列功能,但是它只是一个功能库,并不会执行,只是定义了如何训练
那么我们就需要新写一个执行脚本来调用,他就是我们的train_model.py,这种模块化的设计方便我们更换不同的训练方法
头文件
import os
import numpy as np
import librosa
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import classification_report, confusion_matrix
import joblib
import glob
import time
from audio_emotion import extract_features_from_file
设置输出日志
LOG_FILE = "training_log.txt"
写入输出日志
def log_message(message):print(message)with open(LOG_FILE, "a") as f:timestamp = time.strftime("%Y-%m-%d %H:%M:%S")f.write(f"[{timestamp}] {message}\n")
主函数 main
获取情感类别
emotions = [d for d in os.listdir("dataset") if os.path.isdir(os.path.join("dataset", d))]
初始化特征和标签
features = []labels = []feature_names = None
开始训练
for emotion in emotions:emotion_dir = os.path.join("dataset", emotion)audio_files = glob.glob(os.path.join(emotion_dir, "*.wav"))if not audio_files:log_message(f"警告: {emotion} 类别中没有发现WAV文件。")continuelog_message(f"处理 {len(audio_files)} 个 {emotion} 类别的文件...")for audio_file in audio_files:log_message(f"提取特征: {audio_file}")feature_vector, names = extract_features_from_file(audio_file) # 使用原始函数if feature_vector is not None:features.append(feature_vector)labels.append(emotion)if feature_names is None:feature_names = namesif not features:log_message("错误: 没有成功提取任何特征,请检查音频文件格式。")return# 转换为numpy数组features = np.array(features)labels = np.array(labels)log_message(f"成功提取 {len(features)} 个样本的特征,每个样本 {features.shape[1]} 个特征。")# 划分训练集和测试集X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.2, random_state=42)log_message(f"训练集: {X_train.shape[0]} 个样本,测试集: {X_test.shape[0]} 个样本。")# 训练SVM模型log_message("开始训练SVM模型...")model = SVC(kernel='rbf', probability=True)model.fit(X_train, y_train)log_message("SVM模型训练完成。")# 在测试集上评估y_pred = model.predict(X_test)# 计算分类报告report = classification_report(y_test, y_pred, output_dict=True)# 输出分类报告log_message("\n分类报告:")for emotion in sorted(report.keys()):if emotion != "accuracy" and emotion != "macro avg" and emotion != "weighted avg":precision = report[emotion]['precision']recall = report[emotion]['recall']f1 = report[emotion]['f1-score']support = report[emotion]['support']log_message(f"{emotion}:\t精确率: {precision:.2f}, 召回率: {recall:.2f}, F1: {f1:.2f}, 样本数: {support}")log_message(f"\n整体准确率: {report['accuracy']:.2f}")# 保存混淆矩阵log_message("生成混淆矩阵...")cm = confusion_matrix(y_test, y_pred)plt.figure(figsize=(10, 8))plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)plt.title('混淆矩阵')plt.colorbar()# 添加标签classes = sorted(np.unique(labels))tick_marks = np.arange(len(classes))plt.xticks(tick_marks, classes, rotation=45)plt.yticks(tick_marks, classes)# 在格子中添加数字thresh = cm.max() / 2.for i in range(cm.shape[0]):for j in range(cm.shape[1]):plt.text(j, i, format(cm[i, j], 'd'),horizontalalignment="center",color="white" if cm[i, j] > thresh else "black")plt.ylabel('真实标签')plt.xlabel('预测标签')plt.tight_layout()# 保存混淆矩阵图像plt.savefig('confusion_matrix.png')log_message("混淆矩阵已保存为 confusion_matrix.png")# 保存模型joblib.dump(model, 'emotion_model.pkl')log_message("模型已保存到 emotion_model.pkl")log_message("模型训练和评估完成!")
4.封装部分 main.py
最后我们还需要一个命令行界面用于调用模块、封装框架,他就是main文件
创建项目目录
def create_project_structure():print("开始创建项目目录结构...")os.makedirs("dataset", exist_ok=True)emotions = ["happy", "sad", "angry", "neutral"]for emotion in emotions:os.makedirs(os.path.join("dataset", emotion), exist_ok=True)print("项目目录结构已创建,请将音频文件放入相应的情感文件夹中:")print(" - dataset/happy/")print(" - dataset/sad/")print(" - dataset/angry/")print(" - dataset/neutral/")
提取特征并训练模型
def extract_and_train():if not os.path.exists("dataset"):print("数据集目录不存在,请先运行 'python main.py init'")returnprint("开始提取特征...")try:features, labels, feature_names = extract_features_from_directory("dataset")if len(features) == 0:print("未找到有效的特征数据,请确保数据集中包含.wav文件")returnprint(f"共提取了 {len(features)} 个样本的特征")# 训练模型print("开始训练模型...")model, report, cm, X_test, y_test, y_pred = train_emotion_model(features, labels)# 保存模型save_model(model)# 输出分类报告print("\n分类报告:")for emotion in report.keys():if emotion != "accuracy" and emotion != "macro avg" and emotion != "weighted avg":precision = report[emotion]['precision']recall = report[emotion]['recall']f1 = report[emotion]['f1-score']support = report[emotion]['support']print(f"{emotion}:\t精确率: {precision:.2f}, 召回率: {recall:.2f}, F1: {f1:.2f}, 样本数: {support}")print(f"\n整体准确率: {report['accuracy']:.2f}")# 可视化混淆矩阵classes = np.unique(labels)visualize_confusion_matrix(cm, classes)return modelexcept Exception as e:import tracebackprint(f"训练过程中出错: {str(e)}")traceback.print_exc()return None
预测单个文件情感
def predict_single_file(audio_file):if not os.path.exists("emotion_model.pkl"):print("模型文件不存在,请先训练模型")returnmodel = load_model()prediction, probabilities = predict_emotion(model, audio_file)if prediction is not None:print(f"预测情感: {prediction}")# 获取类别列表classes = model.classes_# 显示各情感的概率print("\n各情感的概率:")for i, emotion in enumerate(classes):print(f"{emotion}: {probabilities[i]:.2f}")# 可视化音频特征process_audio_features(audio_file)else:print("预测失败")
显示
def display_help():print("使用方法:")print(" python main.py init - 创建项目目录结构")print(" python main.py train - 提取特征并训练模型")print(" python main.py predict <audio_file> - 预测单个音频文件的情感")print(" python main.py help - 显示此帮助信息")
主逻辑
if __name__ == "__main__":if len(sys.argv) < 2:display_help()sys.exit(1)command = sys.argv[1].lower()if command == "init":create_project_structure()elif command == "train":extract_and_train()elif command == "predict" and len(sys.argv) >= 3:predict_single_file(sys.argv[2])elif command == "help":display_help()else:print("无效的命令")display_help()sys.exit(1)
5.预测部分 predict.py
一般训练要和预测(也就是使用)部分分离,这样我们就不必每次都重新训练
头文件
import os
import sys
import numpy as np
import librosa
import librosa.display
import matplotlib.pyplot as plt
import joblib
import time
可视化音频特征
def visualize_audio(y, sr, emotion=None):plt.figure(figsize=(12, 8))# 波形plt.subplot(3, 1, 1)librosa.display.waveshow(y, sr=sr)plt.title(f'音频波形 - 预测情感: {emotion}' if emotion else '音频波形')# 梅尔频谱mel_spec = librosa.feature.melspectrogram(y=y, sr=sr)mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)plt.subplot(3, 1, 2)librosa.display.specshow(mel_spec_db, sr=sr, x_axis='time', y_axis='mel')plt.colorbar(format='%+2.0f dB')plt.title('梅尔频谱')# MFCCmfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)plt.subplot(3, 1, 3)librosa.display.specshow(mfccs, sr=sr, x_axis='time')plt.colorbar()plt.title('MFCC')plt.tight_layout()plt.savefig('audio_analysis.png')plt.show()
主逻辑
def main():# 检查命令行参数if len(sys.argv) < 2:print("使用方法: python predict.py <音频文件路径>")returnaudio_file = sys.argv[1]# 检查文件是否存在if not os.path.exists(audio_file):print(f"错误: 文件 {audio_file} 不存在")return# 检查模型文件是否存在model_path = 'emotion_model.pkl'if not os.path.exists(model_path):print(f"错误: 模型文件 {model_path} 不存在,请先运行训练脚本")return# 加载模型print("加载情感识别模型...")model = joblib.load(model_path)# 提取特征print(f"从 {audio_file} 提取特征...")features, feature_names = extract_features_from_file(audio_file) # 使用audio_emotion中的函数# 同时读取音频数据用于可视化y, sr = librosa.load(audio_file, sr=None)if features is None:print("特征提取失败")return# 预测情感features = features.reshape(1, -1)prediction = model.predict(features)[0]probabilities = model.predict_proba(features)[0]print(f"\n预测结果: {prediction}")# 显示各情感的概率print("\n各情感的概率:")for i, emotion in enumerate(model.classes_):print(f"{emotion}: {probabilities[i]:.2f}")# 可视化音频及其特征print("\n生成音频可视化分析...")visualize_audio(y, sr, prediction)print("可视化结果已保存为 audio_analysis.png")if __name__ == "__main__":main()
应用
那么我们后面需要应用模型时只需要在终端执行
python predict.py <处理对象路径>
四.运行展示
下面我们从头到尾执行
初始化目录
python main.py init
生成样本
python generate_samples.py
训练模型
python main.py train
查看结果并分析
open confusion_matrix.png
可以看到模型准确度高达75%,在angry和sad方面尤其精准,说明我们后面需要优化的方面就集中在happy和neutral
应用模型
python predict.py <对象文件路径>
查看分析图
open audio_analysis.png
相关文章:
项目实战-基于信号处理与SVM机器学习的声音情感识别系统
目录 一.背景描述 二.理论部分 三.程序设计 编程思路 流程图 1.信号部分 创建数据 generate_samples.py 头文件 生成函数 generate_emotion_sample 传入参数 存储路径 生成参数 创建基础正弦波信号 调制基础正弦波 对于愤怒可以增加噪声 归一化信号 存储 主函…...
基于Docker的MongoDB环境搭建:从零开始的完整实践指南
在现代应用开发中,容器化技术已成为构建可移植、易维护的服务环境的标准方案。MongoDB作为NoSQL数据库的代表,与Docker结合后能够显著提升部署效率。本文将深入解析如何通过Docker搭建安全可靠的MongoDB环境,涵盖基础配置、数据持久化、权限管理及安全加固等核心环节。 一、…...
C++ 类与对象(下)—— 进阶特性与底层机制解析(构造函数初始化,类型转换,static成员,友元,内部类,匿名对象)
一、构造函数初始化列表:给成员变量 “精准出生证明” 在 C 中,构造函数对成员变量的初始化方式有 初始化列表 和 函数体内赋值 两种。初始化列表是构造函数的一个重要特性,它允许在对象创建时对成员变量进行初始化。与在构造函数体内赋值不同…...
项目生成日志链路id,traceId
Trace 1. 注册filter package com.sc.account.config;import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public cla…...
SQL常见误区
查询的顺序 书写顺序 SELECT 字段列表 FROM 表名列表 WHERE 条件列表 GROUP BY 分组字段列表 HAVING 分组后条件列表 ORDER BY 排序字段列表。。他们的加载顺序 逻辑处理实际顺序 常见错误 在 WHERE 中使用 SELECT 的别名 sql – 错误示例(WHERE 中不能使用别名…...
android zxing QrCode 库集成转竖屏适配问题
由于zxing 这个库使用比较广泛,所以大家也都遇到这个问题了,甚至最早可以追溯到十年前甚至更早,所以原创是谁已经无法找到,表明转载又需要填原文链接,就腆着脸标个原创了,不过的确不是我的原创,…...
实验4 mySQL查询和视图
一、实验目的 掌握SELECT语句的基本语法多表连接查询GROUP BY的使用方法。ORDER BY的使用方法。 二、实验步骤、内容、结果 实验内容: 实验4.1数据库的查询 目的与要求 (1)掌握SELECT语句的基本语法。 (2)掌握子查询的表示。 (3)掌握连接查询的表示。 (4)掌…...
解决用Deveco device tool无法连接local pc
原文链接:https://kashima19960.github.io/2025/05/05/openharmony/解决用Deveco%20device%20tool无法连接local%20pc/ 问题描述 WindowsUbuntu 环境下DevEco tool upload Hi3681开发 烧录 Local PC 箭头红一下,又绿了 用Deveco device tool进行upload…...
Google-chrome版本升级后sogou输入法不工作了
背景: 笔记本Thinkpad E450,操作系统Ubuntu 24.04.2 LTS,Chrome浏览器版本135.0.7049.114-1,Edge浏览器版本131.0.2903.99-1,输入法Sogou版本4.2.1.145 现象: - **正常场景**:Edge中可通过Ctrl…...
C++ 检查某个点是否存在于圆扇区内(Check whether a point exists in circle sector or not)
我们有一个以原点 (0, 0) 为中心的圆。作为输入,我们给出了圆扇区的起始角度和圆扇区的大小(以百分比表示)。 例子: 输入:半径 8 起始角 0 百分比 12 x 3 y 4 输出&am…...
电脑怎么分屏操作?
快捷键分屏 : 在打开两个窗口后,选中一个窗口,按下 “Windows 键 →” 键,该窗口会自动移动到屏幕右侧并占据一半空间,再点击需要分屏的窗口,即可完成分屏。若想恢复窗口为全屏,只需再次按下 …...
深度学习:智能助理从技术演进到全民普惠
在数字化浪潮席卷全球的今天,智能助理已成为人们生活与工作中不可或缺的伙伴。从简单的语音应答到如今具备复杂认知与交互能力,深度学习技术的持续突破,正推动智能助理行业迈向全新高度。深入探究其行业发展、现状、技术演进与实践࿰…...
哈希算法、搜索算法与二分查找算法在 C# 中的实现与应用
在计算机科学中,哈希算法、搜索算法和二分查找算法是三个非常基础且常用的概念。它们分别在数据存储、数据查找、以及高效检索等场景中起着至关重要的作用。在 C# 中,这些算法的实现和使用也十分简便。本文将详细讲解这三种算法的原理、应用以及 C# 中的…...
优化02-执行计划
Oracle 的执行计划(Execution Plan)是数据库优化器(Optimizer)为执行 SQL 语句而选择的操作路径和资源分配方案的详细描述。它记录了数据库如何访问表、索引、连接数据以及执行排序、过滤等操作的步骤。理解执行计划是性能调优的核…...
FreeRTOS菜鸟入门(十一)·信号量·二值、计数、递归以及互斥信号量的区别·优先级翻转以及继承机制详解
目录 1. 信号量的基本概念 2. 分类 2.1 二值信号量 2.2 计数信号量 2.3 互斥信号量 2.4 递归信号量 3. 应用场景 3.1 二值信号量 3.2 计数信号量 3.3 互斥信号量 3.4 递归信号量 4. 运作机制 4.1 二值信号量 4.2 计数信号量 4.3 互斥信号量 4.4…...
C++ -- 内存管理
C --内存管理 1. C/C内存分布2. C中动态内存管理3. C中动态内存管理4. 面对自定义类型5. operator new和operator delete6. new和delete的实现原理6.1 内置类型6.2 自定义类型 7. 定位new(placement new)7.1 底层机制7.2 本质 1. C/C内存分布 2. C中动态…...
基于muduo库实现高并发服务器
文章目录 一、项目介绍二、HTTP服务器1.概念2.Reactor模型2.1单Reactor单线程:单I/O多路复用业务处理2.2单Reactor多线程:单I/O多路复用线程池(业务处理)2.3多Reactor多线程:多I/O多路复用线程池(业务处理&…...
开源PDF解析工具Marker深度解析
开源PDF解析工具Marker深度解析 检索增强生成(RAG)系统的第一步就是做 pdf 解析,从复杂多样的 pdf 中提取出干净准确的文本内容。现有的最优秀的开源工具有两个:Marker 和 MinerU。因为 Marker 是个人开发者做的,文档…...
Redis的内存淘汰机制
Redis的内存淘汰机制和过期策略是2个完全不同的机制, 过期策略指的是使用那种策略来删除过期键,Redis的内存淘汰机制是指:当Redis的运行内存已经超过设置的最大运行内存时,采用什么策略来删除符合条件的键值对,以此来保…...
我国“东数西算”工程对数据中心布局的长期影响
首席数据官高鹏律师团队 我国“东数西算”工程作为国家级战略,旨在优化全国算力资源配置,推动数字经济发展,其对数据中心布局的长期影响主要体现在以下几个方面: 1. 区域协调与资源优化配置 东部与西部分工明确:东部…...
CPT204 Advanced Obejct-Oriented Programming 高级面向对象编程 Pt.10 二叉搜索树
文章目录 1.二叉树(Binary Trees)1.1 二叉搜索树(Binary Search Tree,简称BST)1.1.1 插入操作1.1.2 搜索操作1.1.3 树的遍历(Tree Traversal)1.1.3.1 前序遍历(Preorder Traversal&a…...
MinIO实现https访问
Windows下实现MinIO的https访问. 首先需要自己解决证书问题, 这里可以是个人证书 也可以是花钱买的证书. 现在使用个人开发者证书举例子。 将证书数据解压到你知道的目录之下 然后直接使用命令启动MinIO start minio.exe server --certs-dir D:\xxxxx\tools\certs …...
查看并升级Docker里面Jenkins的Java17到21版本
随着时间推移,java17将逐渐退出舞台,取而代之的是java21。Jenkins也在逐步升级淘汰java版本,今天教大家升级java版本。 Jenkins问题提示 Java 17 end of life in Jenkins You are running Jenkins on Java 17, support for which will end o…...
【KWDB 创作者计划】KWDB 2.2.0多模融合架构与分布式时序引擎
KWDB介绍 KWDB数据库是由开放原子开源基金会孵化的分布式多模数据库,专为AIoT场景设计,支持时序数据、关系数据和非结构化数据的统一管理。其核心架构采用多模融合引擎,集成列式时序存储、行式关系存储及自适应查询优化器,实现跨模…...
Redis的过期设置和策略
Redis设置过期时间主要有以下几个配置方式 expire key seconds 设置key在多少秒之后过期pexpire key milliseconds 设置key在多少毫秒之后过期expireat key timestamp 设置key在具体某个时间戳(timestamp:时间戳 精确到秒)过期pexpireat key millisecon…...
2.3 向量组
本章主要考查向量组的线性关系、秩与极大无关组、向量空间等核心内容,是线性代数的重要基础模块。以下从四个核心考点展开系统梳理: 考点一:向量组的线性表示 核心问题:如何用一组向量线性表出另一组向量?如何判断线性…...
协议(消息)生成
目录 协议(消息)生成主要做什么? 知识点二 制作功能前的准备工作 编辑编辑 制作消息生成功能 实现效果 总结 上一篇中配置的XML文件可见: https://mpbeta.csdn.net/mp_blog/creation/editor/147647176 协议(消息)生成主要做什么? //协议生成 主要是…...
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】4.5 清洗流程自动化(存储过程/定时任务)
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 PostgreSQL数据清洗自动化:存储过程与定时任务全攻略4.5 清洗流程自动化:构建智能数据处理管道4.5.1 存储过程:复杂清洗逻辑封装4.5.1.1 …...
Python中有序序列容器的概念及其与可变性的关系
什么是有序序列容器? 有序序列容器是Python中一类重要的数据类型,它们具有以下共同特征: 元素有序排列:元素按照插入顺序存储,可以通过位置(索引)访问 可迭代:可以使用for循环遍历…...
数据结构实验8.1:图的基本操作
文章目录 一,实验目的二,实验内容三,实验要求四,算法分析五,示例代码8-1.cpp源码graph.h源码 六,操作步骤七,运行结果 一,实验目的 1.掌握图的邻接矩阵、邻接表的表示方…...
PostgreSQL 的 pg_current_wal_lsn 函数
PostgreSQL 的 pg_current_wal_lsn 函数 pg_current_wal_lsn 是 PostgreSQL 中用于获取当前预写式日志(WAL)写入位置的关键函数,对于数据库监控、复制管理和恢复操作至关重要。 一 基本说明 语法 pg_current_wal_lsn() RETURNS pg_lsn功能 返回当前的 WAL 写入…...
P6822 [PA 2012 Finals] Tax 题解
题目大意 可恶,我们老师竟然把紫题放到了模拟赛里。 题目传送门 原题中题意说的很清楚了。 思路 转化问题 首先先新建两条边,使原题点到点的问题转化成边到边的问题。 可以连接一条从 0 0 0 到 1 1 1,长度为 0 0 0 的边,设这条边为 0 0 0 号边。 还可以连接一条…...
Python异步编程入门:从同步到异步的思维转变
引言 作为一名开发者,你可能已经习惯了传统的同步编程模式——代码一行接一行地执行,每个操作都等待前一个操作完成。但在I/O密集型应用中,这种模式会导致大量时间浪费在等待上。今天,我们将探讨Python中的异步编程,这…...
【Python】使用`python-dotenv`模块管理环境变量
最近田辛老师在进行与AI有关的开发。 在开发和部署 Python 应用程序时(要么是在某个Python环境,要么是在MaxKB等知识库系统),我常常需要根据不同的环境(如开发环境、测试环境、生产环境)使用不同的配置信息…...
破局者手册 Ⅰ:测试开发核心基础,解锁未来测试密钥!
目录 一、引入背景 二、软件测试基础概念 2.1 软件测试的定义 2.2 软件测试的重要性 2.3 软件测试的原则 三、测试类型 3.1 功能测试 3.2 接口测试 3.2.1 接口测试的概念 3.2.2 接口测试的重要性 3.2.3 接口测试的要点 3.2.4 接口测试代码示例(Python r…...
物联网mqtt和互联网http协议区别
MQTT和HTTP是两种不同的网络协议,它们在以下方面存在区别: 一、连接方式 1.MQTT:基于TCP/IP协议,采用长连接方式。客户端与服务器建立连接后,会保持连接状态,可随时进行数据传输,适用于实时性…...
C++笔记之反射、Qt中的反射系统、虚幻引擎中的反射系统
C++笔记之反射、Qt中的反射系统、虚幻引擎中的反射系统 code review! 目录 C++笔记之反射、Qt中的反射系统、虚幻引擎中的反射系统 目录1. 反射基础概念 1...
提示词压缩方法总结与开源工具包
论文标题 AN EMPIRICAL STUDY ON PROMPT COMPRESSION FOR LARGE LANGUAGE MODELS 论文地址 https://arxiv.org/pdf/2505.00019 开源地址 https://github.com/3DAgentWorld/Toolkit-for-Prompt-Compression 作者背景 香港科技大学广州校区,华南理工大学&#…...
【AI提示词】AARRR 模型执行者
提示说明 具备完整的产品知识和数据分析能力,擅长通过AARRR模型优化用户生命周期管理,提升企业收入和市场拓展。 提示词 # Role: AARRR 模型执行者## Profile - language: 中文 - description: 具备完整的产品知识和数据分析能力,擅长通过…...
深入理解 Redis 的主从、哨兵与集群架构
目录 前言1 Redis 主从架构1.1 架构概述1.2 优点与应用场景1.3 局限性 2 Redis 哨兵架构2.1 架构概述2.2 高可用能力的实现2.3 局限与注意事项 3 Redis 集群架构3.1 架构概述3.2 高性能与高可用的统一3.3 限制与挑战 4 架构对比与选型建议结语 前言 在构建高性能、高可用的数据…...
基于CBOW模型的词向量训练实战:从原理到PyTorch实现
基于CBOW模型的词向量训练实战:从原理到PyTorch实现 在自然语言处理(NLP)领域,词向量是将单词映射为计算机可处理的数值向量的重要方式。通过词向量,单词之间的语义关系能够以数学形式表达,为后续的文本分…...
【阿里云大模型高级工程师ACP习题集】2.9 大模型应用生产实践(下篇)
练习题 【单选题】在大模型应用备案中,根据《生成式人工智能服务管理暂行办法》,已上架但未完成合规手续的应用应如何处理?( ) A. 继续运营,同时补办手续 B. 下架处理 C. 暂停部分功能,直至完成合规手续 D. 无需处理,等待监管部门通知 【多选题】在应用服务安全的应用部…...
Matlab实现CNN-BiLSTM时间序列预测未来
Matlab实现CNN-BiLSTM时间序列预测未来 目录 Matlab实现CNN-BiLSTM时间序列预测未来效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现CNN-BiLSTM时间序列预测未来; 2.运行环境Matlab2023b及以上,data为数据集,单变量时间序…...
互联网大厂Java求职面试:AI大模型与云原生架构设计深度解析
互联网大厂Java求职面试:AI大模型与云原生架构设计深度解析 第一轮提问:AI大模型与系统集成 技术总监(张总):郑薪苦,你之前提到过Spring AI,那你能讲讲在实际项目中如何将大模型集成到系统中&…...
GD32F103C8T6多串口DMA空闲中断通信程序
以下是一个完全符合C99标准的GD32F103C8T6多串口DMA通信完整实现,代码经过Keil MDK验证并包含详细注释: #include "gd32f10x.h" #include <string.h>/* 硬件配置宏 */ #define USART_NUM 2 /* 使用2个串口 */ #define R…...
labelimg快捷键
一、核心标注快捷键 W:调出标注十字架,开始绘制矩形框(最常用功能)A/D:切换上一张(A)或下一张(D)图片,实现快速导航Del:删除当前选中的标注框 二、文件操作快捷键 CtrlS&…...
【深度学习-Day 6】掌握 NumPy:ndarray 创建、索引、运算与性能优化指南
Langchain系列文章目录 01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...
开元类双端互动组件部署实战全流程教程(第2部分:控制端协议拆解与机器人逻辑调试)
作者:那个写了个机器人结果自己被踢出房间的开发者 游戏逻辑房间结构参考界面 从这张图我们能看出,该组件按功能结构细分为多个房间,每个房间底注、准入标准不同,对应的控制模块也有层级区分。常规来说,一个“互动房间…...
51单片机入门教程——蜂鸣器播放天空之城
前言 本教程基于B站江协科技课程进行个人学习整理,专为拥有C语言基础的零基础入门51单片机新手设计。既帮助解决因时间差导致的设备迭代调试难题,也助力新手快速掌握51单片机核心知识,实现从C语言理论到单片机实践应用的高效过渡 。 目录 …...
linux 历史记录命令
命令方式 #/bin/bash #cd /tmp saveFile"tmp.log" isok"grep HISTTIMEFORMAT /etc/profile|wc -l" if [ $isok -eq 0 ] thenecho -e "#history time\nHISTFILESIZE4000\nHISTSIZE4000\nHISTTIMEFORMAT%F %T \nexport HISTTIMEFORMAT\n" >>…...