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

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

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

PyTorchは、オープンソースのPython向けの機械学習ライブラリ。Facebookの人工知能研究グループが開発を主導しています。強力なGPUサポートを備えたテンソル計算、テープベースの自動微分による柔軟なニューラルネットワークの記述が可能です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

自然言語処理

自然言語処理は、日常的に使用される自然言語をコンピューターに処理させる技術やソフトウェアの総称です。

Q&A

解決済

1回答

5628閲覧

文書の他クラス分類でtorch.Sizeエラーが出る。

coffeebar

総合スコア140

PyTorch

PyTorchは、オープンソースのPython向けの機械学習ライブラリ。Facebookの人工知能研究グループが開発を主導しています。強力なGPUサポートを備えたテンソル計算、テープベースの自動微分による柔軟なニューラルネットワークの記述が可能です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

自然言語処理

自然言語処理は、日常的に使用される自然言語をコンピューターに処理させる技術やソフトウェアの総称です。

0グッド

0クリップ

投稿2021/11/26 07:03

編集2021/11/26 12:36

前提・実現したいこと

サンプルコードを使って、手持ちの文書の5クラス分類をしたいです。
訓練の開始までは進みますが、以下のエラーが出て止まります。

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

ValueError Traceback (most recent call last) <ipython-input-15-ced522624eac> in <module>() 49 50 for epoch in range(max_epoch): ---> 51 train_ = train(model) 52 test_ = validation(model) 53 print(f'epoch {epoch} loss : {test_}') 5 frames /usr/local/lib/python3.7/dist-packages/torch/nn/functional.py in binary_cross_entropy_with_logits(input, target, weight, size_average, reduce, reduction, pos_weight) 2978 2979 if not (target.size() == input.size()): -> 2980 raise ValueError("Target size ({}) must be the same as input size ({})".format(target.size(), input.size())) 2981 2982 return torch.binary_cross_entropy_with_logits(input, target, weight, pos_weight, reduction_enum) ValueError: Target size (torch.Size([32])) must be the same as input size (torch.Size([32, 5]))

該当のソースコード

Google colabでBERTを使ってライブドアニュースコーパスを多クラス分類をする
↑このコードから以下の部分を**「削って」**、手持ちの文書データを入力データ(df)とするように変更しています。

def remove_brackets(inp): # 記号とかを除く brackets_tail = re.compile('【[^】]*】$') brackets_head = re.compile('^【[^】]*】') output = re.sub(brackets_head, '', re.sub(brackets_tail, '', inp)) return output def read_title(f): # 2行スキップ next(f) # URL next(f) # タイムスタンプ title = next(f) # 3行目を返す:タイトル title = remove_brackets(title.decode('utf-8')) return title[:-1] # all_text.tsvを作る with tarfile.open(tgz_fname) as tf: # 対象ファイルの選定 for ti in tf: """ ・ライセンスファイルはスキップ ・genre内のtxt意外ならスキップ ・txtファイル意外ならスキップ ・用意したgenre意外ならスキップ """ if "LICENSE.txt" in ti.name: continue if len(ti.name.split('/')) < 3: continue if not ti.name.endswith(".txt"): continue genre = ti.name.split('/')[1] if not genre in target_genres: continue genre_index = target_genres.index(genre) fname_class_list[target_genres[genre_index]].append(ti.name) with open(tsv_fname, "w") as wf: writer = csv.writer(wf, delimiter='\t') for i, genre in enumerate(target_genres): for fname in fname_class_list[genre]: f = tf.extractfile(fname) title = read_title(f) row = [genre, i, title] writer.writerow(row)
# 作成したデータの読み込み df = pd.read_csv("all_text.tsv", delimiter='\t', header=None, names=['media_name', 'label', 'sentence']) df = df.dropna(how='any') # nanのところは落とす # データの確認 print(f'データサイズ: {df.shape}') display(df.sample(10))

また

# 分類したい種類の対象や数はここで調整する fname_class_list = { "dokujo-tsushin": [], "it-life-hack": [], "kaden-channel": [], "livedoor-homme": [], "movie-enter": [], "peachy": [], "smax": [], "sports-watch": [], "topic-news": [] } target_genres = list(fname_class_list.keys())

fname_class_list = { "class_1": [], "class_2": [], "class_3": [], "class_4": [], "class_5": [], } target_genres = list(fname_class_list.keys())

に修正しています。

試したこと

・ labelsを5列のワンホット・データに変更 → エラー

・ def train(model): と def validation(model): の

loss = F.cross_entropy(outputs.logits, b_labels)

loss = F.cross_entropy(outputs.logits, b_labels.unsqueeze(5))

に変更 → 同じエラーのまま

クラスのタイプをfloatからintに変更したところ、訓練が進むようになりました。
訓練が終わり次第、質問を閉じる予定です。
お手間を取らせて、申し訳ありませんでした。

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

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

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

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

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

jbpb0

2021/11/26 12:24 編集

質問内容と同様なことをGoogle Colabでやってみましたが、大丈夫でした 以下、確認した手順を書きます 下記の内容を20回繰り返して、トータル100行のテキストファイル「all_text2.tsv」を作成し、Google Colabにアップロード (項目の区切り文字はタブ) class_1 0 友人代表のスピーチ、独女はどうこなしている? class_2 1 旧式Macで禁断のパワーアップ!最新PCやソフトを一挙にチェック class_3 2 電力使用量9日が8社管内で今夏最高 class_4 3 フォーエバー21旗艦店が銀座に進出 class_5 4 インタビュー:宮崎あおい&堺雅人「一緒にいるのが当たり前」 https://tech.fusic.co.jp/posts/2021-04-23-bert-multi-classification/ のコードをGoogle Colabにコピペし、質問に記載の変更を行い(ただし「試したこと」はやらない)、さらに下記を変更してから、実行 df = pd.read_csv("all_text.tsv", delimiter='\t', header=None, names=['media_name', 'label', 'sentence']) ↓ アップロードしたファイル名に合わせる df = pd.read_csv("all_text2.tsv", delimiter='\t', header=None, names=['media_name', 'label', 'sentence']) logits_df = pd.DataFrame(preds[0].cpu().numpy(), columns=['logit_0', 'logit_1', 'logit_2', 'logit_3', 'logit_4', 'logit_5', 'logit_6', 'logit_7', 'logit_8']) ↓ 5クラスに合わせる logits_df = pd.DataFrame(preds[0].cpu().numpy(), columns=['logit_0', 'logit_1', 'logit_2', 'logit_3', 'logit_4'])
jbpb0

2021/11/26 12:25 編集

# データの確認 print(f'データサイズ: {df.shape}') display(df.sample(10)) の結果は、下記の通りでした (下記はフォーマットが崩れて表示されますが、実際は項目名と項目が縦に揃ってます) データサイズ: (100, 3) media_name label sentence 38 class_4 3 フォーエバー21旗艦店が銀座に進出 26 class_2 1 旧式Macで禁断のパワーアップ!最新PCやソフトを一挙にチェック 72 class_3 2 電力使用量9日が8社管内で今夏最高 65 class_1 0 友人代表のスピーチ、独女はどうこなしている? 25 class_1 0 友人代表のスピーチ、独女はどうこなしている? 64 class_5 4 インタビュー:宮崎あおい&堺雅人「一緒にいるのが当たり前」 33 class_4 3 フォーエバー21旗艦店が銀座に進出 83 class_4 3 フォーエバー21旗艦店が銀座に進出 9 class_5 4 インタビュー:宮崎あおい&堺雅人「一緒にいるのが当たり前」 32 class_3 2 電力使用量9日が8社管内で今夏最高
coffeebar

2021/11/26 12:28

jbpb0様 動作確認に時間を取って頂き、大変ありがとうございます。 どうやら、私の用意した文書データのクラスのタイプがfloatになっていたのがエラーの原因のようです。 intに変更したところ、訓練が進んでいます。 訓練が終わりましたら、こちらに結果をお示ししようと思います。
guest

回答1

0

自己解決

クラスのタイプがfloatだったのが、エラーの原因だったようです。
intに変更したところ、訓練が完了し 予測も出来ました。
(何故あのエラーにつながるのか、までは分かってませんが...)
調べていただいた方々、お時間を取って頂き ありがとうございました。

投稿2021/11/26 13:57

coffeebar

総合スコア140

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

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

jbpb0

2021/11/27 02:02

https://github.com/huggingface/transformers/blob/master/src/transformers/models/bert/modeling_bert.py の1562行目以降を見ると、「labels」が整数の場合は「CrossEntropyLoss」が呼ばれ、そうでない場合は「BCEWithLogitsLoss」が呼ばれるので、 > クラスのタイプがfloatだった の時は「BCEWithLogitsLoss」が呼ばれたのだと思います https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html の「Shape:」を見ると、「CrossEntropyLoss」ではshapeは Input: (データ数, クラス数) Target: (データ数) です https://pytorch.org/docs/stable/generated/torch.nn.BCEWithLogitsLoss.html の「Shape:」を見ると、「BCEWithLogitsLoss」では「Input」と「Target」のshapeは同じです 「CrossEntropyLoss」では大丈夫な(異なる)shapeの「Input」と「Target」が「BCEWithLogitsLoss」に渡されて、shapeが違うので > Target size (torch.Size([32])) must be the same as input size (torch.Size([32, 5])) となったのではないですかね
coffeebar

2021/11/27 08:53

お時間を取って 詳しく調べて頂き、ありがとうございました。 floatを使うとソフトラベルだと思われて、「BCEWithLogitsLoss」が呼ばれる ということみたいですね。 大変勉強になりました。 jbpb0様のように調べられるよう、精進していきたいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問