axinc-ai / ailia-models

The collection of pre-trained, state-of-the-art AI models for ailia SDK
2.05k stars 326 forks source link

ADD g2p_en #1468

Closed kyakuno closed 5 months ago

kyakuno commented 6 months ago

英語の音素変換。最新版はnumpyになっているので、昔のリビジョンのtensorflowからonnxに変換する。 https://github.com/Kyubyong/g2p/blob/master/g2p_en/g2p.py もしくは、自前でtorchにweightを流し込んでonnxに変換しても良い。

kyakuno commented 5 months ago

@takumi2786 こちら、優先度を少し上げたいと考えていまして、いつ頃、実装できそうでしょうか?

kyakuno commented 5 months ago

g2p_enのv1にして、tensorflow v2に対応するためにplaceholderを書き換える必要がある。 https://v-crn.hatenablog.com/entry/2019/12/20/TensorFlow_2_0_0%E3%81%B8%E3%81%AE%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%A7%E5%87%BA%E3%81%8F%E3%82%8F%E3%81%97%E3%81%9F%E3%82%A8%E3%83%A9%E3%83%BC%EF%BC%9AAttributeError%3A_module_ ただ、v2にはrnnがないので、tensorflow1でエクスポートする必要がある。 https://github.com/tensorflow/tensorflow/issues/32784

kyakuno commented 5 months ago

onnxエクスポートのサンプル。 https://github.com/axinc-ai/export-to-onnx/blob/master/export_from_tensorflow.py

kyakuno commented 5 months ago

tensorflow 1.8のインストールにはpython3.6が必要。 https://qiita.com/Sk_s/items/d6e970d32719d44b8883

kyakuno commented 5 months ago

Ubuntu22.04にはpython3.6が入らないので、諦めてtorchでグラフを再構築した方が良さそう。

kyakuno commented 5 months ago

ChatGPTにtorchに変えてもらった。

g2p_torch.py.zip

original

['AY1', ' ', 'HH', 'AE1', 'V', ' ', 'T', 'UW1', ' ', 'HH', 'AH1', 'N', 'D', 'R', 'AH0', 'D', ' ', 'F', 'IH1', 'F', 'T', 'IY0', ' ', 'D', 'AA1', 'L', 'ER0', 'Z', ' ', 'IH0', 'N', ' ', 'M', 'AY1', ' ', 'P', 'AA1', 'K', 'AH0', 'T', ' ', '.']
['P', 'AA1', 'P', 'Y', 'AH0', 'L', 'ER0', ' ', 'P', 'EH1', 'T', 'S', ' ', ',', ' ', 'F', 'AO1', 'R', ' ', 'IH0', 'G', 'Z', 'AE1', 'M', 'P', 'AH0', 'L', ' ', 'K', 'AE1', 'T', 'S', ' ', 'AH0', 'N', 'D', ' ', 'D', 'AA1', 'G', 'Z']
['AY1', ' ', 'R', 'IH0', 'F', 'Y', 'UW1', 'Z', ' ', 'T', 'UW1', ' ', 'K', 'AH0', 'L', 'EH1', 'K', 'T', ' ', 'DH', 'AH0', ' ', 'R', 'EH1', 'F', 'Y', 'UW2', 'Z', ' ', 'ER0', 'AW1', 'N', 'D', ' ', 'HH', 'IY1', 'R', ' ', '.']
['AY1', 'M', ' ', 'AE1', 'N', ' ', 'AE2', 'K', 'T', 'IH0', 'V', 'EY1', 'SH', 'AH0', 'N', 'IH0', 'S', 'T', ' ', '.']

torch

['AY1', ' ', 'HH', 'AE1', 'V', ' ', 'T', 'UW1', ' ', 'HH', 'AH1', 'N', 'D', 'R', 'AH0', 'D', ' ', 'F', 'IH1', 'F', 'T', 'IY0', ' ', 'D', 'AA1', 'L', 'ER0', 'Z', ' ', 'IH0', 'N', ' ', 'M', 'AY1', ' ', 'P', 'AA1', 'K', 'AH0', 'T', ' ', '.']
['P', 'AA1', 'P', 'Y', 'AH0', 'L', 'ER0', ' ', 'P', 'EH1', 'T', 'S', ' ', ',', ' ', 'F', 'AO1', 'R', ' ', 'IH0', 'G', 'Z', 'AE1', 'M', 'P', 'AH0', 'L', ' ', 'K', 'AE1', 'T', 'S', ' ', 'AH0', 'N', 'D', ' ', 'D', 'AA1', 'G', 'Z']
['AY1', ' ', 'R', 'IH0', 'F', 'Y', 'UW1', 'Z', ' ', 'T', 'UW1', ' ', 'K', 'AH0', 'L', 'EH1', 'K', 'T', ' ', 'DH', 'AH0', ' ', 'R', 'EH1', 'F', 'Y', 'UW2', 'Z', ' ', 'ER0', 'AW1', 'N', 'D', ' ', 'HH', 'IY1', 'R', ' ', '.']
['AY1', 'M', ' ', 'AE1', 'N', ' ', 'AE2', 'K', 'T', 'IH0', 'V', 'EY1', 'SH', 'AH0', 'N', 'IH0', 'S', 'T', ' ', '.']
takumi2786 commented 5 months ago

@kyakuno すみません、6月あまり稼働できておらず、まだ目処はついていないです :bow:

急ぎであれば一旦手放そうかと思いますがどうでしょうか :bow:

kyakuno commented 5 months ago

@takumi2786 承知しました。私の方で作業をしてみます。

takumi2786 commented 5 months ago

@kyakuno すみません、ありがとうございます

kyakuno commented 5 months ago

encoderとdecoderを分離。

g2p_torch_r2.py.zip

kyakuno commented 5 months ago

下記でONNXエクスポートを実施。 https://github.com/axinc-ai/g2p/tree/torch

kyakuno commented 5 months ago

https://storage.googleapis.com/ailia-models/g2p_en/g2p_decoder.onnx https://storage.googleapis.com/ailia-models/g2p_en/g2p_decoder.onnx.prototxt https://storage.googleapis.com/ailia-models/g2p_en/g2p_encoder.onnx https://storage.googleapis.com/ailia-models/g2p_en/g2p_encoder.onnx.prototxt

kyakuno commented 5 months ago

nltk.download('cmudict') で入るのは下記。 https://github.com/nltk/nltk_data/issues/66 ライセンス。 https://github.com/cmusphinx/cmudict/blob/master/LICENSE

kyakuno commented 5 months ago

品詞はnltkのpos_taggerで計算されている。 https://stackoverflow.com/questions/32016545/how-does-nltk-pos-tag-work

kyakuno commented 5 months ago

homographは品詞によって発音が異なることをシミュレートしている。

kyakuno commented 5 months ago

nltkのtaggerもonnxに変換したい。

kyakuno commented 5 months ago

hundredは複数定義されている。

HUNDRED 1 HH AH1 N D R AH0 D
HUNDRED 2 HH AH1 N D R IH0 D
HUNDRED 3 HH AH1 N ER0 D
HUNDRED 4 HH AH1 N D ER0 D

self.cmu[word][0]だと最初のを使う。

kyakuno commented 5 months ago

cmuだと、  RETHINK 1 R IY0 TH IH1 NG K で、 homographsだと、  RETHINK|R IY2 TH IH1 NG K|R IY1 TH IH0 NG K|V で、アクセント記号が異なる。

kyakuno commented 5 months ago

nltkのtag/perceptron.pyのPerceptronTaggerでtaggingされている。

    def tag(self, tokens, return_conf=False, use_tagdict=True):
        """
        Tag tokenized sentences.
        :params tokens: list of word
        :type tokens: list(str)
        """
        prev, prev2 = self.START
        output = []

        context = self.START + [self.normalize(w) for w in tokens] + self.END
        for i, word in enumerate(tokens):
            tag, conf = (
                (self.tagdict.get(word), 1.0) if use_tagdict == True else (None, None)
            )
            print(tag, word)
            if not tag:
                features = self._get_features(i, word, context, prev, prev2)
                tag, conf = self.model.predict(features, return_conf)
            output.append((word, tag, conf) if return_conf == True else (word, tag))

            prev2 = prev
            prev = tag

        return output

tagとwordを表示すると、辞書ベースでwordからtagが決定するものと、AIで決定するものの2種類がある。

, ,
IN for
NN example
None cats
CC and
None dogs
None i
None refuse
TO to
kyakuno commented 5 months ago

_get_featuresでは、前後のtagをもとに、featureを決定する。featureは、activationistだと、

defaultdict(<class 'int'>, {'bias': 1, 'i suffix ist': 1, 'i pref1 a': 1, 'i-1 tag DT': 1, 'i-2 tag VB': 1, 'i tag+i-2 tag DT VB': 1, 'i word activationist': 1, 'i-1 tag+i word DT activationist': 1, 'i-1 word an': 1, 'i-1 suffix an': 1, "i-2 word i'm": 1, 'i+1 word .': 1, 'i+1 suffix .': 1, 'i+2 word -END-': 1})

のような文字列になる。

kyakuno commented 5 months ago

実際の推論は下記のコードで動く。ネットワークはシンプルではある。

    def predict(self, features, return_conf=False):
        """Dot-product the features and current weights and return the best label."""
        scores = defaultdict(float)
        for feat, value in features.items():
            if feat not in self.weights or value == 0:
                continue
            weights = self.weights[feat]
            for label, weight in weights.items():
                scores[label] += value * weight

        # Do a secondary alphabetic sort, for stability
        best_label = max(self.classes, key=lambda label: (scores[label], label))
        # compute the confidence
        conf = max(self._softmax(scores)) if return_conf == True else None

        return best_label, conf
kyakuno commented 5 months ago

onnxの変換で、seq_lenが奇数だと結果が合わなそう。

kyakuno commented 5 months ago

辞書にある単語も常にpredictを通すようにすると、下記の例外になる。

kyakuno@mbakk g2p_en % python3 g2p_en.py --verify
 INFO arg_utils.py (13) : Start!
 INFO arg_utils.py (163) : env_id: 2
 INFO arg_utils.py (166) : MPSDNN-Apple M2
 INFO model_utils.py (89) : ONNX file and Prototxt file are prepared!
 INFO model_utils.py (89) : ONNX file and Prototxt file are prepared!
 INFO model_utils.py (109) : cmudict is prepared!
 INFO model_utils.py (109) : homographs.en is prepared!
 INFO model_utils.py (109) : averaged_perceptron_tagger.pickle is prepared!
 INFO license.py (81) : ailiaへようこそ。ailia SDKは商用ライブラリです。特定の条件下では、無償使用いただけますが、原則として有償ソフトウェアです。詳細は https://ailia.ai/license/ を参照してください。
i have two hundred fifty dollars in my pocket.
Python(24142,0x20281a240) malloc: Incorrect checksum for freed object 0x7fbe241bb400: probably modified after being freed.
Corrupt value: 0x3db1c000bf75c000
Python(24142,0x20281a240) malloc: *** set a breakpoint in malloc_error_break to debug
zsh: abort      python3 g2p_en.py --verify
kyakuno commented 5 months ago

iを入れた時に、shapeが(2,)になり、encoder.runでエラーになる。

kyakuno commented 5 months ago

ailia本体に配列の範囲外参照があるような気もする。

kyakuno commented 5 months ago

onnxruntimeでも例外が出る。

2024-06-26 08:03:39.036948 [E:onnxruntime:, sequential_executor.cc:514 ExecuteKernel] Non-zero status code returned while running Gather node. Name:'/Gather_12' Status Message: indices element out of data bounds, idx=2 must be within the inclusive range [-2,1]
Traceback (most recent call last):
  File "/Users/kyakuno/Desktop/ailia/ailia-models-ax/natural_language_processing/g2p_en/g2p_en.py", line 270, in <module>
    main()
  File "/Users/kyakuno/Desktop/ailia/ailia-models-ax/natural_language_processing/g2p_en/g2p_en.py", line 264, in main
    verify(encoder, decoder)
  File "/Users/kyakuno/Desktop/ailia/ailia-models-ax/natural_language_processing/g2p_en/g2p_en.py", line 234, in verify
    out = g2p(text, encoder, decoder)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/kyakuno/Desktop/ailia/ailia-models-ax/natural_language_processing/g2p_en/g2p_en.py", line 175, in __call__
    pron = self.predict(word, encoder, decoder)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/kyakuno/Desktop/ailia/ailia-models-ax/natural_language_processing/g2p_en/g2p_en.py", line 118, in predict
    h = encoder.run(
        ^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/onnxruntime/capi/onnxruntime_inference_collection.py", line 220, in run
    return self._sess.run(output_names, input_feed, run_options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
onnxruntime.capi.onnxruntime_pybind11_state.InvalidArgument: [ONNXRuntimeError] : 2 : INVALID_ARGUMENT : Non-zero status code returned while running Gather node. Name:'/Gather_12' Status Message: indices element out of data bounds, idx=2 must be within the inclusive range [-2,1]
kyakuno commented 5 months ago

下記でsteps=2でループしているので、シンボル数は2以上である必要がある。

        for t in range(steps):
            h = self.grucell(x[:, t, :], h, w_ih, w_hh, b_ih, b_hh)  # (b, h)
            outputs[:, t, :] = h
        return outputs
kyakuno commented 5 months ago

シンボル数が1の場合は、全て辞書に含まれる想定に見える。

kyakuno commented 5 months ago

have [10 3 24 7 2] でもエラーになる。

onnxruntime.capi.onnxruntime_pybind11_state.InvalidArgument: [ONNXRuntimeError] : 2 : INVALID_ARGUMENT : Non-zero status code returned while running Gather node. Name:'/Gather_24' Status Message: indices element out of data bounds, idx=5 must be within the inclusive range [-5,4]
kyakuno commented 5 months ago

stepsにはx.shape[0]が入るので動いて欲しいが、dynamic shapeがtraceできていない気がする。

kyakuno commented 5 months ago

for stepsがconstantになっている予感。

kyakuno commented 5 months ago

そういうわけではなかった。

kyakuno commented 5 months ago

"i"でエクスポートした場合と、"activationist"でエクスポートした場合で、onnxの深さが変わってしまう。 やはり、シーケンス長が定数になってしまっている。

kyakuno commented 5 months ago

forを外に出した方が良さそう。

kyakuno commented 5 months ago

forをencoderの外に出すことで解消。