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

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

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

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

Q&A

解決済

1回答

1386閲覧

AttributeError: 'str' object has no attribute 'numpy' についての解決方法を教えていただきたいです。

yuncy21

総合スコア2

Python

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

0グッド

0クリップ

投稿2022/11/15 05:54

編集2022/11/15 07:13

前提

bertの勉強をしようと軽く触れた段階です。プログラミング自体初心者です。
https://www.ai-shift.co.jp/techblog/550
勉強にあたって、上記のサイトのコードを実行してみたところ、attributeエラーが出ました。
エラーの意味は分かるのですが、どう修正していけばいいかわかりません。解決方法を教えていただきたいです。

python

1tokens = ["[MASK]" if t == "*" else t for i, t in enumerate(tokens)] 2mask_vecs = outputs[0].numpy()[[i+1 for i in masked_indexs]]

1行目のelseが何故必要なのかわかりません。
2行目のmask_vecsは問題文全体のベクトルということで合っていますでしょうか。
よろしくお願いいたします。

実現したいこと

  • 正常に動作するようにする

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

AttributeError Traceback (most recent call last) <ipython-input-37-2942a8726bf2> in <module> 29 30 part6_slover(text,candidate1,answer1,q=1) ---> 31 part6_slover(text,candidate3,answer1,q=3) <ipython-input-36-75a002ca5230> in part6_slover(text, candidate, answer, q) 14 with torch.no_grad(): 15 outputs, _ = model.bert(ids) ---> 16 mask_vecs = outputs[0].numpy()[[i+1 for i in masked_indexs]] 17 18 c_vecs = np.array([get_bert_vec(c) for c in candidate]) AttributeError: 'str' object has no attribute 'numpy'

該当のソースコード

Python

1def part6_slover(text, candidate, answer, q): 2 if max([len(tokenizer.tokenize(c)) for c in candidate]) == 1: #candidate(候補)を順番に見てすべて1単語であれば 3 return part5_slover(text, candidate, answer) #part5のロジックを使用 4 tokens = tokenizer.tokenize(text) #textをトークン化 5 tokens = ["[MASK]" if t == "*" else t for i, t in enumerate(tokens)] #トークンを順番に見て*を[MASK]に変更 6 tokens = ["[CLS]"] + tokens + ["[SEP]"] #前後に[CLS],[SEP]を付与 7 8 ids = tokenizer.convert_tokens_to_ids(tokens) #id化 9 ids = torch.tensor(ids).reshape(1,-1) #テンソル化 10 ids = ids.cuda() #GPU 11 12 masked_indexs = [i for i, v in enumerate(ids[0]) if v == 103] #[MASK]のid(103)がでてくるのは何番目か 13 14 with torch.no_grad(): #文章ベクトルを計算 15 outputs, _ = model.bert(ids) 16 mask_vecs = outputs[0].numpy()[[i+1 for i in masked_indexs]] #? 17 18 c_vecs = np.array([get_bert_vec(c) for c in candidate]) #選択肢の文章ベクトルを計算 19 return candidate[cosine_similarity([mask_vecs[q-1]], c_vecs)[0].argsort()[-1]] #cos類似度の高いものを戻り値に

コメントは独自に意味を汲み取ったものです。誤った捉え方をしていたら教えてほしいです。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

PondVillege

2022/11/15 06:06

その記法は「リスト内包表記」と呼ばれるものです,そちらに関してご自身で調査いただいて,わからない内容を聞かれるのが建設的かと思います.
pig_vba

2022/11/15 07:15 編集

outputs[0]の中身がstring型になっているのでシステム君が[string型変数にnumpy()ってメソッドなんかないで!]って怒られてます。十中八九呼び出し方かmodel.bertの返り値のどちらかがおかしいのが原因です。私自身もあまり詳しくないのであまり出しゃばらずに修正方法はほかの詳しい人に任せます。 []の記述方法は内包表記と言います。 詳しい解説はこちらを参照ください。 https://aiacademy.jp/media/?p=1252
yuncy21

2022/11/15 06:59

内包表記を調べて、プログラムを見ると、大方の内容は汲み取ることができました。 ありがとうございます。 それでもわからない部分が出てきましたので、質問内容をそのように編集させていただきます。 型の違いについては私の知識ではわかりませんでした...。
guest

回答1

0

ベストアンサー

1行目のelseが何故必要なのかわかりません。

この場合において

Python

1tokens = ["[MASK]" if t == "*" else t for i, t in enumerate(tokens)]

は下記のコードと処理は同じです。

Python

1new_tokens = [] 2for i, t in enumerate(tokens): 3 if t == "*": 4 new_tokens.append("[MASK]") 5 else: 6 new_tokens.append(t) 7tokens = new_tokens

この場合にelseを抜くとtokensには
['[MASK]', '[MASK]', '[MASK]', '[MASK]']
のみが残ります。*を[MASK]に置き換え、それ以外の文字はそのまま残したいので、tが*以外の場合にはtをそのまま追加するという処理をelseを入れることで実現していいます。

2行目のmask_vecsは問題文全体のベクトルということで合っていますでしょうか。

違います。後ほど修正したコードを提示いたしますが、outputs["last_hidden_state"]のshapeは今回の場合、1×144(トークン数)×768です。mask_vecsはその中で[MASK]の部分の最終層の隠れ層のベクトルを表しています。

get_bert_vec関数、part6_slover関数共に

Python

1 with torch.no_grad(): 2 outputs, _ = model.bert(ids)

の部分でoutputsに単なる"last_hideen_state"という文字列を受け取ってしまっているので、そこを下記のように修正して、単なる文字列ではないbertの出力を受け取ることでひとまず動作はするかと思います。

Python

1def get_bert_vec(c): 2 tokens = tokenizer.tokenize(c) 3 ids = tokenizer.convert_tokens_to_ids(tokens) 4 ids = torch.tensor(ids).reshape(1,-1) 5 with torch.no_grad(): 6 outputs = model.bert(ids) 7 vec = outputs["last_hidden_state"][0].numpy().mean(0) 8 return vec 9 10def part6_slover(text, candidate, q): 11 if max([len(tokenizer.tokenize(c)) for c in candidate]) == 1: 12 return part5_slover(text, candidate) 13 tokens = tokenizer.tokenize(text) 14 tokens = ["[MASK]" if t == "*" else t for i, t in enumerate(tokens)] 15 tokens = ["[CLS]"] + tokens + ["[SEP]"] 16 ids = tokenizer.convert_tokens_to_ids(tokens) 17 ids = torch.tensor(ids).reshape(1,-1) 18 masked_indexs = [i for i, v in enumerate(ids[0]) if v == 103] 19 20 with torch.no_grad(): 21 outputs = model.bert(ids) 22 mask_vecs = outputs["last_hidden_state"][0].numpy()[[i+1 for i in masked_indexs]] 23 c_vecs = np.array([get_bert_vec(c) for c in candidate]) 24 return candidate[cosine_similarity([mask_vecs[q-1]], c_vecs)[0].argsort()[-1]]

投稿2022/11/15 20:26

編集2022/11/15 20:27
fixk

総合スコア70

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuncy21

2022/11/17 03:00

回答ありがとうございました。 elseについて、処理をわけたコードを見ることで、かなり理解することができました。 エラーの原因に関しては、["last_hidden_state"]をつけることでベクトルのみを出力することができるんですね。実際に、修正前のoutputsを出力してみるとよくわかりました。 この度は、分かりやすい回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問