hmmlearn拟合MultinomialHMM时维度不匹配错误的技术问询
问题分析与解决
错误原因解析
你遇到的维度不匹配问题,核心是对MultinomialHMM的输入数据格式理解有误:
- 你手动设置了
model.n_features = 4(对应词汇表大小),这代表模型期望每个观测样本是4维的计数向量(对应词汇表中每个类别的出现次数)。 - 但你生成的
observations是(10,7)的数组,每个样本是7个离散取值(属于词汇表),模型把这7当成了特征维度,自然和期望的4不匹配。
另外,lengths参数的用法也有误:它的作用是指定多个观测序列的长度,当你把多个序列拼接成一个一维数组时,用lengths告诉模型每个序列的长度,而非每个样本的长度。
修正后的代码
根据你的需求(离散观测值,每个时间步取词汇表中的一个值),正确实现如下:
import numpy as np from hmmlearn import hmm states = ['up', 'down'] start_probs = np.array([0.6, 0.4]) vocabulary = [0, 1, 2, 3] emission_probs = np.array( [ [0.25, 0.1, 0.4, 0.25], [0.2, 0.5, 0.1, 0.2], ] ) trans_mat = np.array( [ [0.8, 0.2], [0.2, 0.8], ] ) # 生成10个观测序列,每个序列长度为7 sequences = [np.random.choice(vocabulary, 7) for _ in range(10)] # 把所有序列拼接成二维数组(每个观测值单独成一行) observations = np.concatenate(sequences).reshape(-1, 1) # lengths记录每个序列的长度,这里每个序列长度都是7 lengths = [len(seq) for seq in sequences] # 初始化模型:单变量离散观测无需设置n_trials model = hmm.MultinomialHMM( n_components=len(states), n_iter=50, init_params='', ) model.n_features = len(vocabulary) model.startprob_ = start_probs model.transmat_ = trans_mat model.emissionprob_ = emission_probs # 拟合模型 model.fit(observations, lengths) # 解码时传入完整观测数组和序列长度列表 logprob, received = model.decode(observations, lengths) # 将解码结果拆分回对应每个序列的状态 states_per_sequence = np.split(received, np.cumsum(lengths)[:-1])
关键要点说明
- 观测数据格式:对于单变量离散观测(每个时间步一个词汇值),
X需要是形状为(n_total_samples, 1)的二维数组,其中n_total_samples是所有观测序列的总长度。 - lengths参数:必须是一个列表,每个元素对应一个观测序列的长度,列表元素总和等于
X的第一维长度。 - n_trials参数:该参数用于多试验的多项分布观测(比如每个时间步做N次试验,统计每个类别的出现次数),你的场景是单试验(每个时间步一个观测值),因此不需要设置。
内容的提问来源于stack exchange,提问作者zzzbbx
相关产品推荐
相关产品推荐

