TTS | NaturalSpeech语音合成论文详解及项目实现【正在更新中】

 ----------------------------------🔊 语音合成 相关系列直达 🔊 -------------------------------------

✨NaturalSpeech:正在更新中~

✨NaturalSpeech2:TTS | NaturalSpeech2语音合成论文详解及项目实现

本文主要是 讲解了NaturalSpeech论文及项目~

论文题目:202205_NaturalSpeech: End-to-End Text to Speech Synthesis with Human-Level Quality

论文地址:[2205.04421] NaturalSpeech: End-to-End Text to Speech Synthesis with Human-Level Quality (arxiv.org)

代码地址:heatz123/naturalspeech: A fully working pytorch implementation of NaturalSpeech (Tan et al., 2022) (github.com)

1.论文详解

(本博客主要讲解系统实现部分,介绍和背景省略,主要讲解论文第三章)

1.1.设计原理

受图像/视频生成的启发,使用VQ-VAE将高维图像压缩为低维表示以方便生成,该模型利用变分自编码器(Variational Auto-Encoder, VAE),将高维语音x压缩为z表示,相应的先验(记作 p(z|y))则从文本序列 y 中获取。

考虑到来自语音的后验比来自文本的先验更加复杂,研究员们设计了几个模块,尽可能近似地对后验和先验进行匹配,从而通过y→p(z|y)→p(x|z)→x实现文本到语音的合成。

  • 在音素编码器上利用大规模音素预训练(phoneme pre-training),从音素序列中提取更好的表达。
  • 利用由时长预测器和上采样层组成的完全可微分的时长模块(durator),来改进音素的时长建模。
  • 基于流模型(flow)的双向先验/后验模块(bidirectional prior/posterior),可以进一步增强先验 p(z|y) 以及降低后验 q(z|x) 的复杂性。
  • 基于记忆的变分自编码器(Memory VAE),可降低重建波形所需的后验复杂性。

1.2.音素编码

音素编码器θpho音素序列y作为输入,并输出音素隐藏序列,进行大规模音素词典学习,提高音素编码器的表达能力。之前的研究表明,在字母/单词级别进行预学习并将预训练模型应用于音素编码器会导致不一致,并且直接使用音素词典学习具有容量限制,因为音素词汇量太小。为了避免这个问题,使用混合音素预学习,它使用音素和上音素(相邻音素合并在一起)作为模型的输入,如图(c)所示。使用掩码语言建模时,会随机屏蔽一些高音素标记及其对应的音素标记,同时预测掩码音素和高音素。混合音素预训练后,使用预训练模型对TTS系统的音素编码器进行初始化。

1.3.可微分的 Durator

可微分的θdur将音素隐藏序列作为输入,并在帧级输出先前的分布序列,如图(a)所示。事先分发给

p(z'|y;\theta pho,\theta dur) = p(z'|y;\theta pri)

\theta pri= [\theta pho,\theta dur]

用于可微分的\theta pri由几个模块组成

  1. 基于音素编码器的持续时间预测器,用于预测每个音素的持续时间
  2. 一个可训练的上采样层,它利用预测的持续时间来训练投影矩阵,以音素隐藏序列的可微分方式将音素级别缩放到帧级别
  3. 两个附加线性层,用于计算隐藏的均值和方差。

与TTS模型一起,可以以完全可微的方式优化持续时间预测、可训练的上采样层和均值/方差线性层,以减少与先前持续时间预测的学习推理差异。真实持续时间用于训练,预测持续时间用于推理。它以软灵活的方式更好地利用持续时间,而不是硬缩放,从而减轻了持续时间预测不准确的副作用。

1.4.双向先/后验

如图(b)

 双向前/后验模块是降低后验复杂性。选择流模型作为双向先/后验模型,目标函数是使用 KL 散度损失的简化后验函数,

对比实验

1.4.消融实验

推理延迟

对比了模型模块

2.项目实现

2.0.环境设置

git clone https://github.com/heatz123/naturalspeech
cd naturalspeechpip install -r requirements.txtapt-get install espeak
# 准备数据集# 数据预处理
python preprocess.py --text_index 1 --filelists filelists/ljs_audio_text_train_filelist.txt filelists/ljs_audio_text_val_filelist.txt filelists/ljs_audio_text_test_filelist.txt

2.1.数据预处理

2.1.1.LJS数据集

在本项目中,包含了ljs数据集的预处理文件,所以不用单独处理,下载数据集命令

wget https://data.keithito.com/data/speech/LJSpeech-1.1.tar.bz2

tar -xf LJSpeech-1.1.tar.bz2

ln -s LJSpeech-1.1/wavs/ DUMMY1

下载数据集后,要将数据集改为以下格式(也就是将文件夹重命名为DUMMY1

cd durations

tar -xf durations.tar.bz2

将文件夹改为如下格式

2.1.2.自己的数据集

首先确认语言,如果是中文就需要将vits中对于中文的处理代码复制到text文件夹下

mandarin.py【附录1】

text/cleaners.py中添加数据预处理

①添加所需要引用的包:例如

  • from text.mandarin import number_to_chinese, chinese_to_bopomofo, latin_to_bopomofo, chinese_to_romaji, chinese_to_lazy_ipa, chinese_to_ipa, chinese_to_ipa2

②添加数据处理代码,例如

  • chinese_cleaners【附录2】
  • korean_cleaners
  • cjke_cleaners(中日韩英)【附录3】

 复制ljs.json文件,重命名为自己的文件(自定义名称),对数据进行处理

python preprocess_texts.py --text_index 1 --filelists filelists/自己数据_train_filelist.txt filelists/自己数据_val_filelist.txt # python preprocess_texts.py --text_index 1 --filelists filelists/cjke_history_train_filelist.txt filelists/cjke_history_val_filelist.txt --text_cleaners cjke_cleaners2

且数据与数据名称相对应

2.2.训练

2.2.1.训练LJS数据集

python train.py -c configs/ljs.json -m [run_name] --warmup
# python train.py -c configs/ljs.json -m ljs_ns --warmup

 

2.2.2.训练自己的数据集

将之前的vits的预训练模型保存到

 python train.py -c configs/history.json -m his_ns

2.3.推理

3.Naturalspeech与VITS的区别

Naturalspeech 是一种基于 VAE 的模型,它采用多种技术来改进先验并简化后验。它与 VITS 在几个方面不同,包括:

  • 音素预训练:Naturalspeech 在大型文本语料库上使用预训练的音素编码器,该编码器是通过对音素序列进行掩码语言建模获得的。
  • 可微的后验器:后验在帧级别操作,而前验在音素级别操作。Naturalspeech 使用可微分的 durator 来弥合长度差异,从而扩展柔软而灵活的功能。
  • 双向前/后:自然语音通过归一化流来减少后部并增强先验,这在两个方向上映射,具有向前和向后损失。
  • 基于记忆的VAE:通过使用Q-K-V注意力的记忆库进一步增强了先验。

错误与解决

【PS1】ValueError: too many values to unpack (expected 2)

 数据预处理格式不对

数据格式根据自己选择的方式

如果是man

【PS2】KeyError: '`'

 将naturalspeech/text/__init__.py中的cleaned_text_to_sequence改为

sequence = [_symbol_to_id[symbol] for symbol in cleaned_text if symbol in _symbol_to_id.keys()]

【PS3】RuntimeError: stft requires the return_complex parameter be given for real inputs, and will further require that return_complex=True in a future PyTorch release. 

/naturalspeech/utils/mel_processing.py

return_complex=True

【PS4】TypeError: mel() takes 0 positional arguments but 5 were given

库版本问题,此时 librosa版本是0.10.0改为0.9.1或者0.8.0

pip install librosa==0.9.1

【PS5】RuntimeError: mat1 and mat2 shapes cannot be multiplied (80x513 and 1x513)

pytorch包太新了导致的修改mel_processing.py,

83行【onesided=True后增加,return_complex=False】

143行【onesided=True后增加,return_complex=False】

错误总结

出现【PS345】问题的根本原因是torch版本是2.0.1,如果是1.13.1版本不会出现相关问题。

附录

【附录1】中文普通话处理代码

import os
import sys
import re
from pypinyin import lazy_pinyin, BOPOMOFO
import jieba
import cn2an
import logging# List of (Latin alphabet, bopomofo) pairs:
_latin_to_bopomofo = [(re.compile('%s' % x[0], re.IGNORECASE), x[1]) for x in [('a', 'ㄟˉ'),('b', 'ㄅㄧˋ'),('c', 'ㄙㄧˉ'),('d', 'ㄉㄧˋ'),('e', 'ㄧˋ'),('f', 'ㄝˊㄈㄨˋ'),('g', 'ㄐㄧˋ'),('h', 'ㄝˇㄑㄩˋ'),('i', 'ㄞˋ'),('j', 'ㄐㄟˋ'),('k', 'ㄎㄟˋ'),('l', 'ㄝˊㄛˋ'),('m', 'ㄝˊㄇㄨˋ'),('n', 'ㄣˉ'),('o', 'ㄡˉ'),('p', 'ㄆㄧˉ'),('q', 'ㄎㄧㄡˉ'),('r', 'ㄚˋ'),('s', 'ㄝˊㄙˋ'),('t', 'ㄊㄧˋ'),('u', 'ㄧㄡˉ'),('v', 'ㄨㄧˉ'),('w', 'ㄉㄚˋㄅㄨˋㄌㄧㄡˋ'),('x', 'ㄝˉㄎㄨˋㄙˋ'),('y', 'ㄨㄞˋ'),('z', 'ㄗㄟˋ')
]]# List of (bopomofo, romaji) pairs:
_bopomofo_to_romaji = [(re.compile('%s' % x[0]), x[1]) for x in [('ㄅㄛ', 'p⁼wo'),('ㄆㄛ', 'pʰwo'),('ㄇㄛ', 'mwo'),('ㄈㄛ', 'fwo'),('ㄅ', 'p⁼'),('ㄆ', 'pʰ'),('ㄇ', 'm'),('ㄈ', 'f'),('ㄉ', 't⁼'),('ㄊ', 'tʰ'),('ㄋ', 'n'),('ㄌ', 'l'),('ㄍ', 'k⁼'),('ㄎ', 'kʰ'),('ㄏ', 'h'),('ㄐ', 'ʧ⁼'),('ㄑ', 'ʧʰ'),('ㄒ', 'ʃ'),('ㄓ', 'ʦ`⁼'),('ㄔ', 'ʦ`ʰ'),('ㄕ', 's`'),('ㄖ', 'ɹ`'),('ㄗ', 'ʦ⁼'),('ㄘ', 'ʦʰ'),('ㄙ', 's'),('ㄚ', 'a'),('ㄛ', 'o'),('ㄜ', 'ə'),('ㄝ', 'e'),('ㄞ', 'ai'),('ㄟ', 'ei'),('ㄠ', 'au'),('ㄡ', 'ou'),('ㄧㄢ', 'yeNN'),('ㄢ', 'aNN'),('ㄧㄣ', 'iNN'),('ㄣ', 'əNN'),('ㄤ', 'aNg'),('ㄧㄥ', 'iNg'),('ㄨㄥ', 'uNg'),('ㄩㄥ', 'yuNg'),('ㄥ', 'əNg'),('ㄦ', 'əɻ'),('ㄧ', 'i'),('ㄨ', 'u'),('ㄩ', 'ɥ'),('ˉ', '→'),('ˊ', '↑'),('ˇ', '↓↑'),('ˋ', '↓'),('˙', ''),(',', ','),('。', '.'),('!', '!'),('?', '?'),('—', '-')
]]# List of (romaji, ipa) pairs:
_romaji_to_ipa = [(re.compile('%s' % x[0], re.IGNORECASE), x[1]) for x in [('ʃy', 'ʃ'),('ʧʰy', 'ʧʰ'),('ʧ⁼y', 'ʧ⁼'),('NN', 'n'),('Ng', 'ŋ'),('y', 'j'),('h', 'x')
]]# List of (bopomofo, ipa) pairs:
_bopomofo_to_ipa = [(re.compile('%s' % x[0]), x[1]) for x in [('ㄅㄛ', 'p⁼wo'),('ㄆㄛ', 'pʰwo'),('ㄇㄛ', 'mwo'),('ㄈㄛ', 'fwo'),('ㄅ', 'p⁼'),('ㄆ', 'pʰ'),('ㄇ', 'm'),('ㄈ', 'f'),('ㄉ', 't⁼'),('ㄊ', 'tʰ'),('ㄋ', 'n'),('ㄌ', 'l'),('ㄍ', 'k⁼'),('ㄎ', 'kʰ'),('ㄏ', 'x'),('ㄐ', 'tʃ⁼'),('ㄑ', 'tʃʰ'),('ㄒ', 'ʃ'),('ㄓ', 'ts`⁼'),('ㄔ', 'ts`ʰ'),('ㄕ', 's`'),('ㄖ', 'ɹ`'),('ㄗ', 'ts⁼'),('ㄘ', 'tsʰ'),('ㄙ', 's'),('ㄚ', 'a'),('ㄛ', 'o'),('ㄜ', 'ə'),('ㄝ', 'ɛ'),('ㄞ', 'aɪ'),('ㄟ', 'eɪ'),('ㄠ', 'ɑʊ'),('ㄡ', 'oʊ'),('ㄧㄢ', 'jɛn'),('ㄩㄢ', 'ɥæn'),('ㄢ', 'an'),('ㄧㄣ', 'in'),('ㄩㄣ', 'ɥn'),('ㄣ', 'ən'),('ㄤ', 'ɑŋ'),('ㄧㄥ', 'iŋ'),('ㄨㄥ', 'ʊŋ'),('ㄩㄥ', 'jʊŋ'),('ㄥ', 'əŋ'),('ㄦ', 'əɻ'),('ㄧ', 'i'),('ㄨ', 'u'),('ㄩ', 'ɥ'),('ˉ', '→'),('ˊ', '↑'),('ˇ', '↓↑'),('ˋ', '↓'),('˙', ''),(',', ','),('。', '.'),('!', '!'),('?', '?'),('—', '-')
]]# List of (bopomofo, ipa2) pairs:
_bopomofo_to_ipa2 = [(re.compile('%s' % x[0]), x[1]) for x in [('ㄅㄛ', 'pwo'),('ㄆㄛ', 'pʰwo'),('ㄇㄛ', 'mwo'),('ㄈㄛ', 'fwo'),('ㄅ', 'p'),('ㄆ', 'pʰ'),('ㄇ', 'm'),('ㄈ', 'f'),('ㄉ', 't'),('ㄊ', 'tʰ'),('ㄋ', 'n'),('ㄌ', 'l'),('ㄍ', 'k'),('ㄎ', 'kʰ'),('ㄏ', 'h'),('ㄐ', 'tɕ'),('ㄑ', 'tɕʰ'),('ㄒ', 'ɕ'),('ㄓ', 'tʂ'),('ㄔ', 'tʂʰ'),('ㄕ', 'ʂ'),('ㄖ', 'ɻ'),('ㄗ', 'ts'),('ㄘ', 'tsʰ'),('ㄙ', 's'),('ㄚ', 'a'),('ㄛ', 'o'),('ㄜ', 'ɤ'),('ㄝ', 'ɛ'),('ㄞ', 'aɪ'),('ㄟ', 'eɪ'),('ㄠ', 'ɑʊ'),('ㄡ', 'oʊ'),('ㄧㄢ', 'jɛn'),('ㄩㄢ', 'yæn'),('ㄢ', 'an'),('ㄧㄣ', 'in'),('ㄩㄣ', 'yn'),('ㄣ', 'ən'),('ㄤ', 'ɑŋ'),('ㄧㄥ', 'iŋ'),('ㄨㄥ', 'ʊŋ'),('ㄩㄥ', 'jʊŋ'),('ㄥ', 'ɤŋ'),('ㄦ', 'əɻ'),('ㄧ', 'i'),('ㄨ', 'u'),('ㄩ', 'y'),('ˉ', '˥'),('ˊ', '˧˥'),('ˇ', '˨˩˦'),('ˋ', '˥˩'),('˙', ''),(',', ','),('。', '.'),('!', '!'),('?', '?'),('—', '-')
]]def number_to_chinese(text):numbers = re.findall(r'\d+(?:\.?\d+)?', text)for number in numbers:text = text.replace(number, cn2an.an2cn(number), 1)return textdef chinese_to_bopomofo(text):text = text.replace('、', ',').replace(';', ',').replace(':', ',')words = jieba.lcut(text, cut_all=False)text = ''for word in words:bopomofos = lazy_pinyin(word, BOPOMOFO)if not re.search('[\u4e00-\u9fff]', word):text += wordcontinuefor i in range(len(bopomofos)):bopomofos[i] = re.sub(r'([\u3105-\u3129])$', r'\1ˉ', bopomofos[i])if text != '':text += ' 'text += ''.join(bopomofos)return textdef latin_to_bopomofo(text):for regex, replacement in _latin_to_bopomofo:text = re.sub(regex, replacement, text)return textdef bopomofo_to_romaji(text):for regex, replacement in _bopomofo_to_romaji:text = re.sub(regex, replacement, text)return textdef bopomofo_to_ipa(text):for regex, replacement in _bopomofo_to_ipa:text = re.sub(regex, replacement, text)return textdef bopomofo_to_ipa2(text):for regex, replacement in _bopomofo_to_ipa2:text = re.sub(regex, replacement, text)return textdef chinese_to_romaji(text):text = number_to_chinese(text)text = chinese_to_bopomofo(text)text = latin_to_bopomofo(text)text = bopomofo_to_romaji(text)text = re.sub('i([aoe])', r'y\1', text)text = re.sub('u([aoəe])', r'w\1', text)text = re.sub('([ʦsɹ]`[⁼ʰ]?)([→↓↑ ]+|$)',r'\1ɹ`\2', text).replace('ɻ', 'ɹ`')text = re.sub('([ʦs][⁼ʰ]?)([→↓↑ ]+|$)', r'\1ɹ\2', text)return textdef chinese_to_lazy_ipa(text):text = chinese_to_romaji(text)for regex, replacement in _romaji_to_ipa:text = re.sub(regex, replacement, text)return textdef chinese_to_ipa(text):text = number_to_chinese(text)text = chinese_to_bopomofo(text)text = latin_to_bopomofo(text)text = bopomofo_to_ipa(text)text = re.sub('i([aoe])', r'j\1', text)text = re.sub('u([aoəe])', r'w\1', text)text = re.sub('([sɹ]`[⁼ʰ]?)([→↓↑ ]+|$)',r'\1ɹ`\2', text).replace('ɻ', 'ɹ`')text = re.sub('([s][⁼ʰ]?)([→↓↑ ]+|$)', r'\1ɹ\2', text)return textdef chinese_to_ipa2(text):text = number_to_chinese(text)text = chinese_to_bopomofo(text)text = latin_to_bopomofo(text)text = bopomofo_to_ipa2(text)text = re.sub(r'i([aoe])', r'j\1', text)text = re.sub(r'u([aoəe])', r'w\1', text)text = re.sub(r'([ʂɹ]ʰ?)([˩˨˧˦˥ ]+|$)', r'\1ʅ\2', text)text = re.sub(r'(sʰ?)([˩˨˧˦˥ ]+|$)', r'\1ɿ\2', text)return text

附录2 中文

def chinese_cleaners(text):'''Pipeline for Chinese text'''text = number_to_chinese(text)text = chinese_to_bopomofo(text)text = latin_to_bopomofo(text)text = re.sub(r'([ˉˊˇˋ˙])$', r'\1。', text)return text

附录3 多语言处理

def cjke_cleaners(text):text = re.sub(r'\[ZH\](.*?)\[ZH\]', lambda x: chinese_to_lazy_ipa(x.group(1)).replace('ʧ', 'tʃ').replace('ʦ', 'ts').replace('ɥan', 'ɥæn')+' ', text)text = re.sub(r'\[JA\](.*?)\[JA\]', lambda x: japanese_to_ipa(x.group(1)).replace('ʧ', 'tʃ').replace('ʦ', 'ts').replace('ɥan', 'ɥæn').replace('ʥ', 'dz')+' ', text)text = re.sub(r'\[KO\](.*?)\[KO\]',lambda x: korean_to_ipa(x.group(1))+' ', text)text = re.sub(r'\[EN\](.*?)\[EN\]', lambda x: english_to_ipa2(x.group(1)).replace('ɑ', 'a').replace('ɔ', 'o').replace('ɛ', 'e').replace('ɪ', 'i').replace('ʊ', 'u')+' ', text)text = re.sub(r'\s+$', '', text)text = re.sub(r'([^\.,!\?\-…~])$', r'\1.', text)return textdef cjke_cleaners2(text):text = re.sub(r'\[ZH\](.*?)\[ZH\]',lambda x: chinese_to_ipa(x.group(1))+' ', text)text = re.sub(r'\[JA\](.*?)\[JA\]',lambda x: japanese_to_ipa2(x.group(1))+' ', text)text = re.sub(r'\[KO\](.*?)\[KO\]',lambda x: korean_to_ipa(x.group(1))+' ', text)text = re.sub(r'\[EN\](.*?)\[EN\]',lambda x: english_to_ipa2(x.group(1))+' ', text)text = re.sub(r'\s+$', '', text)text = re.sub(r'([^\.,!\?\-…~])$', r'\1.', text)return text

自定义requirements.txt

Cython>=0.29.21
librosa>=0.8.0
matplotlib>=3.3.1
numpy>=1.18.5
phonemizer>=2.2.1
scipy>=1.5.2
tensorboard>=2.3.0
torch>=1.6.0
torchvision>=0.7.0
Unidecode>=1.1.1pysoundfile==0.9.0.post1
jamo==0.4.1
ko_pron==1.3
g2pk2
mecab
python-mecab-ko

 

参考文献

【1】NaturalSpeech模型合成语音在CMOS测试中首次达到真人语音水平 - 知乎 (zhihu.com) 

【2】[논문리뷰] NaturalSpeech: End-to-End Text to Speech Synthesis with Human-Level Quality - 전생했더니 인공지능이었던 건에 대하여 (kimjy99.github.io)

【3】NaturalSpeech模型合成语音在CMOS测试中首次达到真人语音水平 (msra.cn) 

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

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

相关文章

基于孔雀优化算法的航线规划

MATLAB2020a下正常运行 上传明细-CSDN创作中心

Excel中部分sheet页隐藏并设置访问密码

1、新建sheet1 2、新建sheet2 3、隐藏sheet2 4、保护工作簿、输密码 5、密码二次确认 6、隐藏的sheet2已经查看不了 7、想要查看时,按图示输入原密码即可 8、查看sheet2内容

【软件工程】航行敏捷之路:深度解析Scrum框架的精髓

🍎个人博客:个人主页 🏆个人专栏: 软件工程 ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 Scrum(敏捷开发框架之一) 详细介绍和解释: 优缺点: 优点: 缺点&…

【MySQL】数据库之高级SQL查询语句补充

目录 一、补充正则表达式的查询regexp 二、补充case的用法 三、补充空值和null值的区别 一、补充正则表达式的查询regexp 要知道 在MySQL中使用正则表达式,一定要在前面加上regexp 正则表达式 ^ 匹配文本的开始字符 ‘^bd’ 匹配以 bd 开头的字符串 …

开关电源输入输出电压测试方法:如何用开关电源智能测试系统测试输入输出电压?

一、用万用表测量输入输出电压 1. 连接万用表到电路中 2. 将万用表调到直流电压挡,连接红表笔到开关电源正极,连接黑表笔到开关电源负极。 3. 打开电源,读取万用表显示的电压值。 二、用示波器测量输入输出电压 1. 连接示波器到电路中 2. 将示…

网络安全—PKI公钥基础设施

文章目录 前提知识散列函数非对称加密数字签名 PKI受信任的人RA注册CA颁发IKE数字签名认证(交换证书)密钥管理 前提知识 散列函数 散列也可以叫哈希函数,MD5、SHA-1、SHA-2、、(不管叫啥,都记得是同一个东西就行&…

图神经网络——图学习

图学习 0. 前言1. 图2. 图学习3. 图神经网络小结 0. 前言 近年来,从社交网络到分子生物学等各个领域,数据的图表示越来越普遍。图神经网络 (Graph Neural Network, GNN) 是专为处理图结构数据而设计的,要充分挖掘图表示的潜力,深…

log4cplus visual c++ 编译及调试小记

简介 最近在调试一款SATA加密设备,发现设备有时加密出来的数据,再解密时与明文对不上,怀疑是通信问题。因此,急需要在测试工具中加入通信日志。由于对第三方日志库都不熟悉,所以随便选了个log4cplus软件集成到现有工具…

Easy Rules规则引擎实战

文章目录 简介pom 规则抽象规则Rule基础规则BasicRule事实类Facts:map条件接口动作接口 四种规则定义方式注解方式RuleBuilder 链式Mvel和Spel表达式Yml配置 常用规则类DefaultRuleSpELRule(Spring的表达式注入) 组合规则UnitRuleGroup 规则引…

009、引用

1. 引用与借用 下面的示例重新定义了一个新的 calculate_length 函数。与之前不同的是,新的函数签名使用了 String 的引用作为参数而没有直接转移值的所有权: fn main() { let s1 String::from("hello"); let len calculate_length(&s1…

Java学习,一文掌握Java之SpringBoot框架学习文集(1)

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。 🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。 🎉欢迎 👍点赞✍评论…

我有实体店,为什么要做小程序

做小程序对于实体店来说有以下几个好处: 拓展线上渠道:随着移动互联网的普及,越来越多的消费者习惯在手机上进行购物和搜索相关信息。通过做小程序,你可以将线下实体店与线上渠道相结合,提供在线购买、预约、查询等功能…

Windows搭建Emby媒体库服务器,无公网IP远程访问本地影音文件

文章目录 1.前言2. Emby网站搭建2.1. Emby下载和安装2.2 Emby网页测试 3. 本地网页发布3.1 注册并安装cpolar内网穿透3.2 Cpolar云端设置3.3 Cpolar内网穿透本地设置 4.公网访问测试5.结语 1.前言 在现代五花八门的网络应用场景中,观看视频绝对是主力应用场景之一&…

pycharm中Pyside2/QtDesigner安装和配置

目录 1、安装pyqt5 2、安装pyqt5-tools 3、在pycharm中配置Qt Designer PyQt5/QtDesigner安装和配置 1、安装pyqt5 pip install pyqt5 安装了 pyqt5 之后,在 python 安装目录下面的 Scripts 文件夹中,有一个 pyuic5.exe 文件,这个可执行文…

大数据概念:数据网格和DataOps

数据网格(Data Mesh) 一种新型的数据架构模式,旨在解决传统数据架构中存在的一些问题,例如数据孤岛、数据冗余、数据安全等。数据网格将数据作为一种服务,通过在分布式环境中提供数据服务,实现数据的共享和…

c++ 静态联编+动态联编 (多态)

静态多态 动态多态 1)静态多态和动态多态的区别就是函数地址是早绑定(静态联编)还是晚绑定(动态联编)。 如果函数的调用,在编译阶段就可以确定函数的调用地址,并产生代码,就是静态多态(编译时多态),就是说地址是早绑定…

Flink实时电商数仓(十)

common模块回顾 app BaseApp: 作为其他子模块中使用Flink - StreamAPI的父类,实现了StreamAPI中的通用逻辑,在其他子模块中只需编写关于数据处理的核心逻辑。BaseSQLApp: 作为其他子模块中使用Flink- SQLAPI的父类。在里面设置了使用SQL API的环境、并行…

数据库攻防学习之Redis

Redis 0x01 redis学习 在渗透测试面试或者网络安全面试中可能会常问redis未授权等一些知识,那么什么是redis?redis就是个数据库,常见端口为6379,常见漏洞为未授权访问。 0x02 环境搭建 这里可以自己搭建一个redis环境&#xf…

文件监控软件丨文件权限管理工具

文件已经成为企业最重要的资产之一。然而,文件的安全性和完整性经常受到威胁,如恶意软件感染、人为误操作、内部泄密等。 为了确保文件的安全,文件监控软件应运而生。本文将深入探讨文件监控软件的概念、功能、应用场景和未来发展等方面。 文…

7、InternVL

简介 github demo 使用网络获取的油画图片,InternVL识别还算可以。 使用stable diffusion生成的图片,InternVL能很好的识别。 权重 huggingface地址 模型搭建 github地址 下载源码 git clone https://github.com/OpenGVLab/InternVL.git创建环…