Python语音基础操作--10.2隐马尔科夫模型的孤立字识别

2023-12-19 01:18

本文主要是介绍Python语音基础操作--10.2隐马尔科夫模型的孤立字识别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《语音信号处理试验教程》(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的。使用CSDN博客查看帮助文件:

Python语音基础操作–2.1语音录制,播放,读取
Python语音基础操作–2.2语音编辑
Python语音基础操作–2.3声强与响度
Python语音基础操作–2.4语音信号生成
Python语音基础操作–3.1语音分帧与加窗
Python语音基础操作–3.2短时时域分析
Python语音基础操作–3.3短时频域分析
Python语音基础操作–3.4倒谱分析与MFCC系数
Python语音基础操作–4.1语音端点检测
Python语音基础操作–4.2基音周期检测
Python语音基础操作–4.3共振峰估计
Python语音基础操作–5.1自适应滤波
Python语音基础操作–5.2谱减法
Python语音基础操作–5.4小波分解
Python语音基础操作–6.1PCM编码
Python语音基础操作–6.2LPC编码
Python语音基础操作–6.3ADPCM编码
Python语音基础操作–7.1帧合并
Python语音基础操作–7.2LPC的语音合成
Python语音基础操作–10.1基于动态时间规整(DTW)的孤立字语音识别试验
Python语音基础操作–10.2隐马尔科夫模型的孤立字识别
Python语音基础操作–11.1矢量量化(VQ)的说话人情感识别
Python语音基础操作–11.2基于GMM的说话人识别模型
Python语音基础操作–12.1基于KNN的情感识别
Python语音基础操作–12.2基于神经网络的情感识别
Python语音基础操作–12.3基于支持向量机SVM的语音情感识别
Python语音基础操作–12.4基于LDA,PCA的语音情感识别

代码可在Github上下载:busyyang/python_sound_open

隐马尔科夫模型(Hidden Markov Models, HMM)作为语音信号的一种统计模型,在语音处理中得到广泛应用。

一个用于语音识别的HMM通常用三组模型参数 M = { A , B , π } \bold{M=\{A,B,\pi\}} M={A,B,π}来定义,假设某HMM一共有N个状态 { S i } i − 1 N \{S_i\}_{i-1}^N {Si}i1N,那么参数的定义为:
A \bold{A} A:状态转移概率矩阵;
A = [ a 11 . . . a 1 N . . . . . . . . . a N 1 . . . a N N ] A=\begin{bmatrix} a_{11}& ...& a_{1N}\\...&...&...\\a_{N1}&...&a_{NN} \end{bmatrix} A=a11...aN1.........a1N...aNN

其中 a i j a_{ij} aij是从状态 S i S_i Si到状态 S j S_j Sj转移时的转移概率,并且 0 ⩽ a i j ⩽ 1 , ∑ i = 1 N a i j = 1 0\leqslant a_{ij}\leqslant 1,\sum_{i=1}^Na_{ij}=1 0aij1,i=1Naij=1

π \pi π:系统初始状态概率的集合, { π } i = 1 N \{\pi\}_{i=1}^N {π}i=1N表示初始状态是 s i s_i si的概率,即: π i = P [ S 1 = s i ] ( 1 ⩽ i ⩽ N ) , ∑ i = 1 N π i j = 1 \pi_i=P[S_1=s_i](1\leqslant i\leqslant N),\sum_{i=1}^N\pi_{ij}=1 πi=P[S1=si](1iN),i=1Nπij=1
B \bold{B} B:处处观测值概率集合, B = { b i j ( k ) } \bold{B}=\{b_{ij}(k)\} B={bij(k)},其中 b i j ( k ) b_{ij}(k) bij(k)是从状态 S i S_i Si到状态 S j S_j Sj转移时,观测值为k的输出概率。根据观察集合 X X X的取值可将HMM分为连续型和离散型。

前向-后向算法

用来计算给定观测值序列 O = o 1 o 2 . . . o T \bold{O}=o_1o_2...o_T O=o1o2...oT以及一个模型 M = { A , B , π } \bold{M=\{A,B,\pi\}} M={A,B,π}时,由模型 M M M产生出 O O O的概率 P ( O ∣ M ) \bold{P(O|M)} P(OM),设 S 1 S_1 S1是初始状态, S N S_N SN是终了状态,则前向-后向算法描述如下:
(1)前向算法
根据输出观察值序列重前向后递推计算输出序列;

符号函数
O = o 1 o 2 . . . o T \bold{O}=o_1o_2...o_T O=o1o2...oT输出观察序列列表
P ( O ∥ M ) \bold{P(O\|M)} P(OM)给定模型M时,输出符号序列O的概率
a i j a_{ij} aij状态 S i S_i Si到状态 S j S_j Sj的转移概率
b i j ( o t ) b_{ij}(o_t) bij(ot)状态 S i S_i Si到状态 S j S_j Sj的转移时输出 o t o_t ot的概率
α t ( j ) \bold{\alpha_t(j)} αt(j)输出部分符号序列 o 1 o 2 . . . o t o_1o_2...o_t o1o2...ot并到达状态 S j S_j Sj的概率(前向概率)

α t ( j ) \bold{\alpha_t(j)} αt(j)可以由递推计算:初始化为 α 0 ( 1 ) = 1 , α 0 ( j ) = 0 ( j ≠ 1 ) \bold{\alpha_0(1)}=1,\bold{\alpha_0(j)}=0(j\neq 1) α0(1)=1,α0(j)=0(j=1)

递推公式为:
α t ( j ) = ∑ i α t − 1 ( i ) a i j b i j ( o t ) , ( t = 1 , 2 , . . . , T ; i , j = 1 , 2 , . . . , N ) \bold{\alpha_t}(j)=\sum_i\bold{\alpha_{t-1}}(i)a_{ij}b_{ij}(o_t),(t=1,2,...,T;i,j=1,2,...,N) αt(j)=iαt1(i)aijbij(ot),(t=1,2,...,T;i,j=1,2,...,N)

最后结果:
P ( O ∣ M ) = α T ( N ) \bold{P(O|M)}=\bold{\alpha_T}(N) P(OM)=αT(N)

t时刻的 α t ( j ) \bold{\alpha_t}(j) αt(j)等于t-1时刻的所有状态的 α t − 1 ( i ) a i j b i j ( o t ) \bold{\alpha_{t-1}}(i)a_{ij}b_{ij}(o_t) αt1(i)aijbij(ot)的和,如果状态 S i S_i Si到状态 S j S_j Sj没有转移时, a i j = 0 a_{ij}=0 aij=0.前向算法计算量大大减小,为 N ( N + 1 ) ( T − 1 ) N(N+1)(T-1) N(N+1)(T1)次乘法和 N ( N − 1 ) ( T + 1 ) N(N-1)(T+1) N(N1)(T+1)次加法。
(2)后向算法
定义 β t ( i ) \bold{\beta}_t(i) βt(i)为后向概率,即从状态 S i S_i Si开始到状态 S N S_N SN结束输出部分符号序列为 o t + 1 , o t + 2 , . . . , o T o_{t+1},o_{t+2},...,o_{T} ot+1,ot+2,...,oT的概率,初始化: β T ( N ) = 1 , β T ( j ) = 0 , ( j ≠ N ) \bold{\beta_T(N)}=1,\bold{\beta_T(j)}=0,(j\neq N) βT(N)=1,βT(j)=0,(j=N)
递推公式:
β t ( i ) = ∑ j β t + 1 ( j ) a i j b i j ( o t + 1 ) , ( t = T , T − 1 , . . . , 1 ; i , j = 1 , 2 , . . . , N ) \bold{\beta}_t(i)=\sum_j\beta_{t+1}(j)a_{ij}b_{ij}(o_{t+1}),(t=T,T-1,...,1;i,j=1,2,...,N) βt(i)=jβt+1(j)aijbij(ot+1),(t=T,T1,...,1;i,j=1,2,...,N)

所以: P ( O ∣ M ) = ∑ i = 1 N β 1 ( i ) π i = β 0 ( 1 ) \bold{P(O|M)}=\sum\limits_{i=1}^N\beta_1(i)\pi_i=\beta_0(1) P(OM)=i=1Nβ1(i)πi=β0(1)

后向计算的计算量为 N 2 T N^2T N2T,根据定义可以知道: P ( O ∣ M ) = ∑ i = 1 N ∑ j = 1 N α t ( i ) a i j b i j ( o t + 1 ) β t + 1 ( j ) \bold{P(O|M)}=\sum\limits_{i=1}^N\sum\limits_{j=1}^N\alpha_t(i)a_{ij}b_{ij}(o_{t+1})\beta_{t+1}(j) P(OM)=i=1Nj=1Nαt(i)aijbij(ot+1)βt+1(j)

维特比(Viterbi)算法

Viterbi解决的是给定观察符号序列 O = o 1 o 2 . . . o T O=o_1o_2...o_T O=o1o2...oT和模型 M = { A , B , π } \bold{M=\{A,B,\pi\}} M={A,B,π},求出状态序列 S = s 1 s 2 . . . s T S=s_1s_2...s_T S=s1s2...sT的问题。最佳意义上的状态序列是使 P ( S , O ∣ M ) P(S,O|M) P(S,OM)最大时确定的状态序列,即HMM输出一个观察值序列 O = o 1 o 2 . . . o T O=o_1o_2...o_T O=o1o2...oT时,可能通过的状态序列有多种,这里面使输出概率最大的序列状态。
初始化: α 0 ′ ( 1 ) = 1 , α 0 ′ ( j ) = 0 ( j ≠ 1 ) \alpha_0'(1)=1,\alpha_0'(j)=0(j\neq 1) α0(1)=1,α0(j)=0(j=1)
递推公式: α t ′ ( j ) = max ⁡ i α t − 1 ′ ( j − 1 ) a i j b i j ( o t ) , ( t = 1 , 2 , . . . , T ; i , j = 1 , 2 , . . . , N ) \alpha_t'(j)=\underset{i}{\max}\alpha_{t-1}'(j-1)a_{ij}b_{ij}(o_t),(t=1,2,...,T;i,j=1,2,...,N) αt(j)=imaxαt1(j1)aijbij(ot),(t=1,2,...,T;i,j=1,2,...,N)
最后: P max ⁡ ( S , O ∣ M ) = α T ′ ( N ) P_{\max}(S,O|M)=\alpha_T'(N) Pmax(S,OM)=αT(N)
每一次使 α t ′ ( j ) \alpha_t'(j) αt(j)最大的状态i组成的状态序列就是所求的最佳状态序列。求最佳状态序列的方式为:
1)给定每个状态准备一个数组变量 α t ′ ( j ) \alpha_t'(j) αt(j),初始化时,令初始状态 S 1 S_1 S1的数组变量 α 0 ′ ( 1 ) = 1 \alpha_0'(1)=1 α0(1)=1,其他状态 α 0 ′ ( j ) = 0 \alpha_0'(j)=0 α0(j)=0
2)根据t时刻输出的观察符号 o t o_t ot计算 α t ′ ( j ) = max ⁡ i α t − 1 ′ a i j b i j ( o t ) = max ⁡ i { α t − 1 ′ a 1 j b 1 j ( o t ) , α t − 1 ′ a 2 j b 2 j ( o t ) , . . . , α t − 1 ′ a N j b N j ( o t ) } \alpha_t'(j)=\underset{i}{\max}\alpha_{t-1}'a_{ij}b_{ij}(o_t)=\underset{i}{\max}\{\alpha_{t-1}'a_{1j}b_{1j}(o_t),\alpha_{t-1}'a_{2j}b_{2j}(o_t),...,\alpha_{t-1}'a_{Nj}b_{Nj}(o_t)\} αt(j)=imaxαt1aijbij(ot)=imax{αt1a1jb1j(ot),αt1a2jb2j(ot),...,αt1aNjbNj(ot)},当状态 S i S_i Si到状态 S j S_j Sj没有转移时, a i j = 0 a_{ij}=0 aij=0。设计一个符号数组变量,称为追加状态序列寄存器,利用这个最佳状态序列寄存器吧每次使得 α t ′ ( j ) \alpha_t'(j) αt(j)最大的状态保存下来。
3)当 t ≠ T t\neq T t=T时转移到2),否则转移到4)。
4)把最终的状态寄存器 α T ′ ( N ) \alpha_T'(N) αT(N)内的值取出,则 P max ⁡ ( S , O ∣ M ) = α T ′ ( N ) P_{\max}(S,O|M)=\alpha_T'(N) Pmax(S,OM)=αT(N)为最佳状态序列寄存器的值,就是所求的最佳状态序列。

Baum-Welch算法

Baum-Welch算法解决的是HMM训练,即HMM参数估计问题,给定一个观察序列 O = o 1 o 2 . . . o T O=o_1o_2...o_T O=o1o2...oT,该算法能确定一个 M = { A , B , π } M=\{A,B,\pi\} M={A,B,π},使 P ( O ∣ M ) P(O|M) P(OM)最大,这是一个泛函极值问题。由于给定的训练序列有限,因而不存在一个最佳的方法来估计模型,Baum-Welch算法也是利用递归思想,使 P ( O ∣ M ) P(O|M) P(OM)局部放大后,最后得到优化的模型参数 M = { A , B , π } M=\{A,B,\pi\} M={A,B,π}。利用Baum-Welch算法重估公式得到的新模型 M ^ \hat M M^,一定有 P ( O ∣ M ^ ) > P ( O ∣ M ) P(O|\hat M)>P(O|M) P(OM^)>P(OM),重复估计过程,直到 P ( O ∣ M ^ ) P(O|\hat M) P(OM^)收敛,不再明显增大,此时的 M ^ \hat M M^即为所求模型。

给定一个观察值符号序列 O = o 1 o 2 . . . o T O=o_1o_2...o_T O=o1o2...oT,以及一个需要通过训练进行重估计参数的HMM模型 M = { A , B , π } M=\{A,B,\pi\} M={A,B,π},按前向-后向算法,设对于符号序列,在时刻t从状态 S i S_i Si到状态 S j S_j Sj的转移概率为 γ t ( i , j ) \gamma_t(i,j) γt(i,j):
γ t ( i , j ) = α t − 1 ( i ) a i j b i j ( o t ) β t ( j ) α T ( N ) = α t − 1 ( i ) a i j b i j ( o t ) β t ( j ) ∑ i α t ( i ) β t ( i ) \gamma_t(i,j)=\frac{\alpha_{t-1}(i)a_{ij}b_{ij}(o_t)\beta_t(j)}{\alpha_T(N)}=\frac{\alpha_{t-1}(i)a_{ij}b_{ij}(o_t)\beta_t(j)}{\sum_i\alpha_t(i)\beta_t(i)} γt(i,j)=αT(N)αt1(i)aijbij(ot)βt(j)=iαt(i)βt(i)αt1(i)aijbij(ot)βt(j)

同时,对于符号序列 O = o 1 o 2 . . . o T O=o_1o_2...o_T O=o1o2...oT,在t时刻的Markov链处于状态 S i S_i Si的概率为:
∑ j = 1 N γ t ( i , j ) = α t ( i ) β t ( i ) ∑ i α t ( i ) β t ( i ) \sum\limits_{j=1}^N\gamma_t(i,j)=\frac{\alpha_t(i)\beta_t(i)}{\sum_i\alpha_t(i)\beta_t(i)} j=1Nγt(i,j)=iαt(i)βt(i)αt(i)βt(i)

这时,状态 S i S_i Si到状态 S j S_j Sj转移次数的期望为 ∑ t γ t ( i , j ) \sum_t\gamma_t(i,j) tγt(i,j),而从状态 S i S_i Si转移出去的次数期望为 ∑ j ∑ t γ t ( i , j ) \sum_j\sum_t\gamma_t(i,j) jtγt(i,j),所以重估公式为:
a ^ i j = ∑ t γ t ( i , j ) ∑ j ∑ t γ t ( i , j ) = ∑ t α t − 1 ( i ) a i j b i j ( o t ) β t ( j ) ∑ t α t ( i ) β t ( i ) \hat a_{ij}=\frac{\sum_t\gamma_t(i,j)}{\sum_j\sum_t\gamma_t(i,j)}=\frac{\sum_t\alpha_{t-1}(i)a_{ij}b_{ij}(o_t)\beta_t(j)}{\sum_t\alpha_t(i)\beta_t(i)} a^ij=jtγt(i,j)tγt(i,j)=tαt(i)βt(i)tαt1(i)aijbij(ot)βt(j)

b ^ i j = ∑ t : o t = k γ t ( i , j ) ∑ t γ t ( i , j ) = ∑ t : o t = k α t − 1 ( i ) a i j b i j ( o t ) β t ( j ) ∑ t α t − 1 ( i ) a i j b i j ( o t ) β t ( j ) \hat b_{ij}=\frac{\sum\limits_{t:o_t=k}\gamma_t(i,j)}{\sum_t\gamma_t(i,j)}=\frac{\sum\limits_{t:o_t=k}\alpha_{t-1}(i)a_{ij}b_{ij}(o_t)\beta_t(j)}{\sum_t\alpha_{t-1}(i)a_{ij}b_{ij}(o_t)\beta_t(j)} b^ij=tγt(i,j)t:ot=kγt(i,j)=tαt1(i)aijbij(ot)βt(j)t:ot=kαt1(i)aijbij(ot)βt(j)

得到的新模型就是 M ^ = { A ^ , B ^ , π ^ } \hat M=\{\hat A,\hat B,\hat\pi\} M^={A^,B^,π^}
具体的实现步骤为:
1)适当地选择 a i j a_{ij} aij b i j ( k ) b_{ij}(k) bij(k)的初始值,常用的设定方式为:给予从状态i转移出去的每条弧相等的转移概率,即
a i j = 1 从 状 态 i 转 移 出 去 的 弧 的 条 数 a_{ij}=\frac{1}{从状态i转移出去的弧的条数} aij=i1

给予每个输出观察符号相等的输出概率初始值,即:
b i j ( k ) = 1 码 本 中 码 字 的 个 数 b_{ij}(k)=\frac{1}{码本中码字的个数} bij(k)=1

并且每条弧上给予相同的输出概率矩阵。
2)给定一个(训练)观察值符号序列 O = o 1 o 2 . . . o T O=o_1o_2...o_T O=o1o2...oT,由初始模型计算 γ t ( i , j ) \gamma_t(i,j) γt(i,j),并且由重估公式,计算 a ^ i j \hat a_{ij} a^ij b ^ i j ( k ) \hat b_{ij}(k) b^ij(k).
3)再给定一个(训练)观察值序列 O = o 1 o 2 . . . o T O=o_1o_2...o_T O=o1o2...oT,吧前一次的 a ^ i j \hat a_{ij} a^ij b ^ i j ( k ) \hat b_{ij}(k) b^ij(k)作为初始模型计算 γ t ( i , j ) \gamma_t(i,j) γt(i,j),重新计算 a ^ i j \hat a_{ij} a^ij b ^ i j ( k ) \hat b_{ij}(k) b^ij(k).
4)直到 a ^ i j \hat a_{ij} a^ij b ^ i j ( k ) \hat b_{ij}(k) b^ij(k)收敛为止。

语音识别一般采用从左到右的HMM,所以初始状态概率 π i \pi_i πi不需要顾及,总设定为:
π 1 = 1 , π i = 0 , ( i = 2 , . . . , N ) \pi_1=1,\pi_i=0,(i=2,...,N) π1=1,πi=0,(i=2,...,N)

from chapter3_分析实验.mel import Nmfcc
from scipy.io import wavfile, loadmat
from hmmlearn import hmm
from sklearn.externals import joblib
import numpy as np
import os"""
代码来自:https://blog.csdn.net/chinatelecom08/article/details/82901480
并进行了部分更改
"""def gen_wavlist(wavpath):"""得到数据文件序列:param wavpath::return:"""wavdict = {}labeldict = {}for (dirpath, dirnames, filenames) in os.walk(wavpath):for filename in filenames:if filename.endswith('.wav'):filepath = os.sep.join([dirpath, filename])fileid = filename.strip('.wav')wavdict[fileid] = filepathlabel = fileid.split('_')[1]labeldict[fileid] = labelreturn wavdict, labeldictdef compute_mfcc(file):"""读取数据并计算mfcc:param file: 文件名:return: mfcc系数""""""有手动修改wavfile.read()函数的返回值,添加了bit_depth的返回,如果报错,修改调用方式为:fs, audio = wavfile.read(file)2020-3-20   Jie Y."""fs, audio, bits = wavfile.read(file)"""由于部分信号太短而报错,所以fs//2了"""mfcc = Nmfcc(audio, fs // 2, 12, frameSize=int(fs // 2 * 0.025), inc=int(fs // 2 * 0.01))return mfcc'''
&usage:		搭建HMM-GMM的孤立词识别模型
参数意义:CATEGORY:	所有标签的列表n_comp:		每个孤立词中的状态数n_mix:		每个状态包含的混合高斯数量cov_type:	协方差矩阵的类型n_iter:		训练迭代次数
'''class Model:def __init__(self, CATEGORY=None, n_comp=3, n_mix=3, cov_type='diag', n_iter=1000):super(Model, self).__init__()self.CATEGORY = CATEGORYself.category = len(CATEGORY)self.n_comp = n_compself.n_mix = n_mixself.cov_type = cov_typeself.n_iter = n_iter# 关键步骤,初始化models,返回特定参数的模型的列表self.models = []for k in range(self.category):model = hmm.GMMHMM(n_components=self.n_comp, n_mix=self.n_mix, covariance_type=self.cov_type,n_iter=self.n_iter)self.models.append(model)def train(self, tdata):for i in range(tdata.shape[1]):model = self.models[i]for x in range(tdata[0, i].shape[1]):data = tdata[0, i][0, x].squeeze()mfcc = Nmfcc(data, 8000, 24, 256, 80)model.fit(mfcc)def test(self, pdata):label = []result = []for k in range(pdata.shape[1]):for i in range(pdata[0, k].shape[1]):label.append(str(k + 1))data = pdata[0, k][0, i].squeeze()mfcc = Nmfcc(data, 8000, 24, 256, 80)result_one = []for m in range(self.category):model = self.models[m]re = model.score(mfcc)result_one.append(re)result.append(self.CATEGORY[np.argmax(np.array(result_one))])print('识别得到结果:\n', result)print('原始标签类别:\n', label)# 检查识别率,为:正确识别的个数/总数totalnum = len(label)correctnum = 0for i in range(totalnum):if result[i] == label[i]:correctnum += 1print('识别率:', correctnum / totalnum)def save(self, path="models.pkl"):joblib.dump(self.models, path)def load(self, path="models.pkl"):self.models = joblib.load(path)tdata = loadmat('tra_data.mat')['tdata']
pdata = loadmat('rec_data.mat')['rdata']CATEGORY = [str(i + 1) for i in range(tdata.shape[1])]
# 进行训练
models = Model(CATEGORY=CATEGORY)
models.train(tdata)
models.test(tdata)
models.test(pdata)

这篇关于Python语音基础操作--10.2隐马尔科夫模型的孤立字识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/510430

相关文章

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

Python版本与package版本兼容性检查方法总结

《Python版本与package版本兼容性检查方法总结》:本文主要介绍Python版本与package版本兼容性检查方法的相关资料,文中提供四种检查方法,分别是pip查询、conda管理、PyP... 目录引言为什么会出现兼容性问题方法一:用 pip 官方命令查询可用版本方法二:conda 管理包环境方法

基于Python开发Windows自动更新控制工具

《基于Python开发Windows自动更新控制工具》在当今数字化时代,操作系统更新已成为计算机维护的重要组成部分,本文介绍一款基于Python和PyQt5的Windows自动更新控制工具,有需要的可... 目录设计原理与技术实现系统架构概述数学建模工具界面完整代码实现技术深度分析多层级控制理论服务层控制注

pycharm跑python项目易出错的问题总结

《pycharm跑python项目易出错的问题总结》:本文主要介绍pycharm跑python项目易出错问题的相关资料,当你在PyCharm中运行Python程序时遇到报错,可以按照以下步骤进行排... 1. 一定不要在pycharm终端里面创建环境安装别人的项目子模块等,有可能出现的问题就是你不报错都安装

使用Java填充Word模板的操作指南

《使用Java填充Word模板的操作指南》本文介绍了Java填充Word模板的实现方法,包括文本、列表和复选框的填充,首先通过Word域功能设置模板变量,然后使用poi-tl、aspose-words... 目录前言一、设置word模板普通字段列表字段复选框二、代码1. 引入POM2. 模板放入项目3.代码

Python打包成exe常用的四种方法小结

《Python打包成exe常用的四种方法小结》本文主要介绍了Python打包成exe常用的四种方法,包括PyInstaller、cx_Freeze、Py2exe、Nuitka,文中通过示例代码介绍的非... 目录一.PyInstaller11.安装:2. PyInstaller常用参数下面是pyinstal