質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

解決済

python negative dimensions are not allowed エラーを解決できません

toommauts
toommauts

総合スコア2

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1回答

0リアクション

0クリップ

2587閲覧

投稿2021/10/29 02:36

前提・実現したいこと

「pythonで学ぶ音声認識」という本を勉強していのですが、MFCC特徴量を計算するプログラムを実行すると

ValueError: negative dimensions are not allowed

というエラーが出てしまい、実行することができません。ネットで調べたところ「サイズの大きく、かつ、スパースなndarrayを操作すると発生する」ようで、その記事の方はnumpy.floatで表現できる最小値を代入して解決したようなのですが、今回扱っているのがInt型でうまく応用できていません。どうしたらいいでしょうか?

使用しているOSはMacOSで、anacondaで仮想環境を立ててjupyternotebookでソースコードを書いています。

発生している問題・エラーメッセージ


ValueError Traceback (most recent call last) <ipython-input-5-4bcd799c2d54> in <module> 337 338 # MFCCを計算する --> 339 mfcc = feat_extractor.ComputeMFCC(waveform) 340 341 # 特徴量のフレーム数と次元数を取得 <ipython-input-5-4bcd799c2d54> in ComputeMFCC(self, waveform) 237 ''' 238 # FBANKおよび対数パワーを計算する --> 239 fbank, log_power = self.ComputeFBANK(waveform) 240 241 # DCTの基底行列との内積により,DCTを実施する <ipython-input-5-4bcd799c2d54> in ComputeFBANK(self, waveform) 171 num_frames = (num_samples - self.frame_size) // self.frame_shift + 1 172 # メルフィルタバンク特徴 --> 173 fbank_features = np.zeros((num_frames, self.num_mel_bins)) 174 # 対数パワー(MFCC特徴を求める際に使用する) 175 log_power = np.zeros(num_frames) ValueError: negative dimensions are not allowed

該当のソースコード

python

-*- coding: utf-8 -*- MFCC特徴の計算を行います. wavデータを読み込むためのモジュール(wave)をインポート import wave 数値演算用モジュール(numpy)をインポート import numpy as np os, sysモジュールをインポート import os import sys class FeatureExtractor(): ''' 特徴量(FBANK, MFCC)を抽出するクラス sample_frequency: 入力波形のサンプリング周波数 [Hz] frame_length: フレームサイズ [ミリ秒] frame_shift: 分析間隔(フレームシフト) [ミリ秒] num_mel_bins: メルフィルタバンクの数(=FBANK特徴の次元数) num_ceps: MFCC特徴の次元数(0次元目を含む) lifter_coef: リフタリング処理のパラメータ low_frequency: 低周波数帯域除去のカットオフ周波数 [Hz] high_frequency: 高周波数帯域除去のカットオフ周波数 [Hz] dither: ディザリング処理のパラメータ(雑音の強さ) ''' クラスを呼び出した時点で最初に1回実行される関数 def __init__(self, sample_frequency=16000, frame_length=25, frame_shift=10, num_mel_bins=23, num_ceps=13, lifter_coef=22, low_frequency=20, high_frequency=8000, dither=1.0): サンプリング周波数[Hz] self.sample_freq = sample_frequency 窓幅をミリ秒からサンプル数へ変換 self.frame_size = int(sample_frequency * frame_length * 0.001) フレームシフトをミリ秒からサンプル数へ変換 self.frame_shift = int(sample_frequency * frame_shift * 0.001) メルフィルタバンクの数 self.num_mel_bins = num_mel_bins MFCCの次元数(0次含む) self.num_ceps = num_ceps リフタリングのパラメータ self.lifter_coef = lifter_coef 低周波数帯域除去のカットオフ周波数[Hz] self.low_frequency = low_frequency 高周波数帯域除去のカットオフ周波数[Hz] self.high_frequency = high_frequency ディザリング係数 self.dither_coef = dither FFTのポイント数 = 窓幅以上の2のべき乗 self.fft_size = 1 while self.fft_size < self.frame_size: self.fft_size *= 2 メルフィルタバンクを作成する self.mel_filter_bank = self.MakeMelFilterBank() 離散コサイン変換(DCT)の基底行列を作成する self.dct_matrix = self.MakeDCTMatrix() リフタ(lifter)を作成する self.lifter = self.MakeLifter() def ComputeFBANK(self, waveform): '''メルフィルタバンク特徴(FBANK)を計算する 出力1: fbank_features: メルフィルタバンク特徴 出力2: log_power: 対数パワー値(MFCC抽出時に使用) ''' 波形データの総サンプル数 num_samples = np.size(waveform) 特徴量の総フレーム数を計算する num_frames = (num_samples - self.frame_size) // self.frame_shift + 1 メルフィルタバンク特徴 fbank_features = np.zeros((num_frames, self.num_mel_bins)) 対数パワー(MFCC特徴を求める際に使用する) log_power = np.zeros(num_frames) 1フレームずつ特徴量を計算する for frame in range(num_frames): 分析の開始位置は,フレーム番号(0始まり)*フレームシフト start_index = frame * self.frame_shift 1フレーム分の波形を抽出し,前処理を実施する. また対数パワーの値も得る window, log_pow = self.ExtractWindow(waveform, start_index, num_samples) 高速フーリエ変換(FFT)を実行 spectrum = np.fft.fft(window, n=self.fft_size) FFT結果の右半分(負の周波数成分)を取り除く ※Kaldiの実装ではナイキスト周波数成分(最後の+1)は捨てているが, 本実装では捨てずに用いている spectrum = spectrum[:int(self.fft_size/2) + 1] パワースペクトルを計算する spectrum = np.abs(spectrum) ** 2 メルフィルタバンクを畳み込む fbank = np.dot(spectrum, self.mel_filter_bank.T) 対数計算時に-infが出力されないよう,フロアリング処理を行う fbank[fbank<0.1] = 0.1 対数をとってfbank_featuresに加える fbank_features[frame] = np.log(fbank) 対数パワーの値をlog_powerに加える log_power[frame] = log_pow return fbank_features, log_power def ComputeMFCC(self, waveform): ''' MFCCを計算する ''' FBANKおよび対数パワーを計算する fbank, log_power = self.ComputeFBANK(waveform) DCTの基底行列との内積により,DCTを実施する mfcc = np.dot(fbank, self.dct_matrix.T) リフタリングを行う mfcc *= self.lifter MFCCの0次元目を,前処理をする前の波形の対数パワーに置き換える mfcc[:,0] = log_power return mfcc メイン関数 if __name__ == "__main__": 設定ここから 各wavファイルのリストと特徴量の出力先 wav_dir = './wav' out_dir = './mfcc' repeat500内で使用するセット数 num_set = 5 repeat500内で使用する1セットあたりの発話数 num_utt_per_set = 10 サンプリング周波数 [Hz] sample_frequency = 16000 フレーム長 [ミリ秒] frame_length = 25 フレームシフト [ミリ秒] frame_shift = 10 低周波数帯域除去のカットオフ周波数 [Hz] low_frequency = 20 高周波数帯域除去のカットオフ周波数 [Hz] high_frequency = sample_frequency / 2 メルフィルタバンクの数 num_mel_bins = 23 MFCCの次元数 num_ceps = 13 ディザリングの係数 dither=1.0 乱数シードの設定(ディザリング処理結果の再現性を担保) np.random.seed(seed=0) 特徴量抽出クラスを呼び出す feat_extractor = FeatureExtractor( sample_frequency=sample_frequency, frame_length=frame_length, frame_shift=frame_shift, num_mel_bins=num_mel_bins, num_ceps=num_ceps, low_frequency=low_frequency, high_frequency=high_frequency, dither=dither) 出力ディレクトリが存在しない場合は作成する os.makedirs(out_dir, exist_ok=True) セット x 発話数分だけ処理を実行 for set_id in range(num_set): for utt_id in range(num_utt_per_set): # wavファイル名 filename = 'REPEAT500_set%d_%03d' % (set_id+1, utt_id+1) wav_path = os.path.join(wav_dir, filename+'.wav') print(wav_path) wavファイルを読み込み,特徴量を計算する with wave.open(wav_path) as wav: サンプリング周波数のチェック if wav.getframerate() != sample_frequency: sys.stderr.write('The expected \ sampling rate is 16000.\n') exit(1) wavファイルが1チャネル(モノラル) データであることをチェック if wav.getnchannels() != 1: sys.stderr.write('This program \ supports monaural wav file only.\n') exit(1) wavデータのサンプル数 num_samples = wav.getnframes() wavデータを読み込む waveform = wav.readframes(num_samples) 読み込んだデータはバイナリ値 (16bit integer)なので,数値(整数)に変換する waveform = np.frombuffer(waveform, dtype=np.int16) MFCCを計算する mfcc = feat_extractor.ComputeMFCC(waveform) 特徴量のフレーム数と次元数を取得 (num_frames, num_dims) = np.shape(mfcc) 特徴量ファイルの名前(splitextで拡張子を取り除いている) out_file = os.path.splitext(os.path.basename(wav_path))[0] out_file = os.path.join(os.path.abspath(out_dir), out_file + '.bin') データをfloat32形式に変換 mfcc = mfcc.astype(np.float32) データをファイルに出力 mfcc.tofile(out_file)

試したこと

np.zerosをnp.onesに変えて全部1を代入するようにしましたが同じようなエラーが出てしまいました。

補足情報(FW/ツールのバージョンなど)

python 3.8.8

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

jbpb0

2021/10/29 03:04

エラーが出てる行のすぐ上に下記を追加して実行したら、何て表示されますでしょうか? print(num_frames) print(self.num_mel_bins)
toommauts

2021/10/29 04:16

-2 23 と表示されました。
jbpb0

2021/10/29 04:45 編集

「-2」はダメですよね その数字のサイズの配列を作るのだから num_frames = (num_samples - self.frame_size) // self.frame_shift + 1 の計算に使ってる各変数の値をprint()で表示させて、それぞれがどのような数値ではないといけないのかを別途考えて、どれが間違ってるのかを特定します そして、間違ってる変数を計算してるところで同様にして、間違ってる原因を遡って特定します
toommauts

2021/10/29 05:09

アドバイスしていただきありがとうございます。 num_samplesがどうやらおかしいので、それを手がかりに調べてみます。
jbpb0

2021/10/29 05:15

num_frames =... がマイナスだから、おそらく num_samples - self.frame_size がマイナスなので、「num_samples」と「self.frame_size」の数値の大小を比較します 「num_samples」は、すぐ上の num_samples = np.size(waveform) でいくつになってるか? それが、解析してるデータのサイズと合ってるか? 「self.frame_size」は、 self.frame_size = int(sample_frequency * frame_length * 0.001) で、いくつになってるか? それを計算してる「sample_frequency」や「frame_length」は正しい数値か? コードの「設定ここから」の下で設定してる数値が、正しくそこに代入されてるか? コードの「設定ここから」の下で設定してる数値は、解析条件に合致した適切な数値か? みたいなことを考えながら確認していき、エラーの原因を探します

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。