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

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

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

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

WSL(Windows Subsystem for Linux)

WSL (Windows Subsystem for Linux) は、Windows10のOS上でLinux向けのバイナリプログラムを実行可能にする機能です。また、WindowsOSのAPIを用いた仕組みを提供しており、Linux側からWindowsOSへのファイルアクセスもできます。

PyTorch

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

Python 3.x

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

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Q&A

解決済

1回答

14769閲覧

pytorchで自作データセットを作成し画像の分類をしたい(init,len,getitemのながれ)

oinari03

総合スコア59

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

WSL(Windows Subsystem for Linux)

WSL (Windows Subsystem for Linux) は、Windows10のOS上でLinux向けのバイナリプログラムを実行可能にする機能です。また、WindowsOSのAPIを用いた仕組みを提供しており、Linux側からWindowsOSへのファイルアクセスもできます。

PyTorch

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

Python 3.x

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

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

0グッド

0クリップ

投稿2020/08/06 08:47

編集2020/08/07 07:05

はじめまして

deeplearning初学者です。
ただやりたいことがあってどうしても全体像からこの辺はどうなっているんだってのを聞きたくてここに書きました。

やりたいこと

・cifer10の画像分類問題を自分で集めた画像だけで実装したい
・フォルダにあるいくつかの画像を分類し、ラベルを付与することです。
ディレクトリ構成(train:val=7:3)

├─animal_dataset ├─train │ ├─cat(70枚くらい) │ └─dog(70枚くらい) └─val ├─cat(30枚くらい) └─dog(30枚くらい)

とりあえず書いてみたコード

・スクレイピングの処理は省いています
・前処理としてtrainとvalそれぞれにかける
・データセットを作成する。
・initの中身にからのdataとlabelを用意する
・画像を呼び出す処理をする??
・for分とif文でディレクトリ名?が一致していたら0/1で場合分けしてlabelのlistに格納
・これで呼び出すときlabelとして機能する?
・lenでデータ数を返す
・getitemでindex番目の画像をロードしたい
・ただ本当にロードできてる?
・ちゃんとlabelとして認識できてる?

全体的に
正しい書き方というのがあいまいです。もう少しきれいなコードできれいにlabel分類したいです。

python

1import torch 2import torch.utils.data as data 3from torchvision import transforms 4from torchvision import datasets, transforms 5import numpy as np 6 7import os 8import glob 9 10 11 12 13 14 15# 前処理 16 17class MyTransform(): 18 def __init__(self, resize, mean, std): 19 self.resize = resize 20 self.mean = mean 21 self.std = std 22 23 def __call__(self,img, key ='train'): 24 data_transform = { 25 'train': transforms.Compose( 26 [transforms.Resize((256,256)), 27 transforms.ToTensor(), 28 transforms.Normalize(self.mean, self.std) #標準化 29 ]), 30 'val': transforms.Compose( 31 [transforms.Resize((256,256)), 32 transforms.ToTensor(), 33 transforms.Normalize(self.mean, self.std) 34 ]) 35 } 36 37 return data_transform[key](img) 38 39 40 41 42# データセット作成 43class MyDatasets(data.Dataset): 44 def __init__(self, path=None, key='train', transform=None): 45 self.transform = transform 46 self.key = key 47 self.path = path 48 self.data = [] 49 self.lables = [] 50 51 target_path = os.path.join(self.path + self.key + '/**/*.jpg') 52 53 for i in glob(target_path): 54 # データリスト作成 55 self.data.append(i) 56 57 #ラベルリスト作成 58 label = os.path.basename(os.path.dirname(i)) 59 if label == "cat": 60 label = 0 61 elif label == "dog": 62 label = 1 63 self.lables.append(label) 64 65 66 # データ数を返す。 67 def __len__(self): 68 return len(self.data) 69 70 # dataとlabelを返すはず 71 def __getitem__(self, index): 72 # index番目の画像をロード 73 img_path = self.data[index] 74 img = Image.open(img) 75 76 img_transformed = self.transform(img, self.key) 77 label = self.labels[index] 78 79 80 return img_transformed, label 81 82 83train_dataset = MyDatasets() 84print(train_dataset.label) 85 86 87 88

error

こちらのコードを実行した結果です。画像の読み込みに失敗しているきがしますがどのように書き換えればいいのかわかりません。

Traceback (most recent call last): File "dataset.py", line 90, in <module> train_dataset = MyDatasets() File "dataset.py", line 59, in __init__ target_path = os.path.join(self.path + self.key + '/**/*.jpg') TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'

参考にしたサイト

自分でこんな感じのものを作りたい
ciffer10のチュートリアル。これを発展させたい感じ

最後に

初心者故、ごちゃごちゃな質問をしてしまったのは否めないです。ただ理解があいまいなためうまく質問もできない状況です。

以下が聞きたいことのまとめかと思いますが補足情報などありましたらお願いします。
・画像の読み込み方
おそらく画像の読み込みに失敗していると思いますので別の方法があれば教えていただきたいです。

・init,getitemの書き方が正しいのか確認してほしいです。
前処理としてこんな内容でいいのかわかりませんが、initの中身、getitemでどんなコードを書いたら紐づけができるのか想像ができません。

・前処理というか上記で上げたコードとして不備はないかを確認してほしいです。
とは言ってもほとんど書けなかったので、何を追加すればいいのか、こんな処理を入れたらもっと良くなる、こう書くのが普通だよ。などを教えてもらえるとありがたいです。

以上
自分のしたいことを具体的に書いたつもりですが不明点などありましたらご指摘下さい。

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

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

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

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

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

aokikenichi

2020/08/06 09:06

参照されている https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html の「4. Train the network」の項に # get the inputs; data is a list of [inputs, labels] とありますが、これで分からないならば基礎を学ぶしかないかと。 画像分類の解説記事は多数ありますが、それが見つからないとのことであれば入門書を読んでコード写経 するのが一番近道だと思います。
oinari03

2020/08/07 03:00

そこに書いてある通りinput,lablesをlist形式で渡すなどっていうのは何となくわかるのですが、 ではそれのlabelをどう用意するのか、どこで書くのが適切かみたいなところがわからなかったりするわけです。 おっしゃるとおりで基礎や入門をするべきでしょうが、pytorchの入門書はあらかた調べましたが、様々な既存データセットについては確認できましたが、自作データセットを扱っているような書籍は見当たらず、その辺を応用できるような力もなかったので困っている次第です。 もし、そのようなアドバイスなどがありましたらよろしくお願いします。
guest

回答1

0

ベストアンサー

質問のコードでエラーが起こっている原因

train_dataset = MyDatasets() で引数を指定していないので、self.path が None になっています。

それを以下で文字列と結合しようとして、None と str の結合はできないとエラーになっています。

python

1target_path = os.path.join(self.path + self.key + '/**/*.jpg')

提案

animal_dataset ├─train │ ├─cat(70枚くらい) │ └─dog(70枚くらい) └─val ├─cat(30枚くらい) └─dog(30枚くらい)

このフォルダ構成であれば、MyDatasets を自作しなくても、torchvision.datasets.ImageFolder が使えます。
ラベルはフォルダ名から自動で作られます。

import torchvision.datasets as datasets # 学習用のデータセット train_dataset = datasets.ImageFolder("animal_dataset/train") # 推論用のデータセット test_dataset = datasets.ImageFolder("animal_dataset/test")

参考リンク ↓ ImageFolder を使った学習の例
Pytorch - 事前学習モデルを使ってクラス分類モデルを学習する方法 - pystyle

追記

python

1import glob 2import os 3 4from PIL import Image 5from torch.utils import data as data 6from torchvision import transforms as transforms 7 8 9class MyDatasets(data.Dataset): 10 def __init__(self, root_dir, key, transform): 11 self.transform = transform 12 self.data = [] 13 self.labels = [] 14 name_to_label = {"cat": 0, "dog": 1} 15 16 target_path_list = [] 17 target_dir = os.path.join(root_dir, key, "**/*") 18 19 for path in glob.glob(target_dir): 20 name = os.path.basename(os.path.dirname(path)) 21 label = name_to_label[name] 22 23 self.data.append(path) 24 self.labels.append(label) 25 26 def __len__(self): 27 return len(self.data) 28 29 def __getitem__(self, index): 30 img_path = self.data[index] 31 label = self.labels[index] 32 33 img = Image.open(img_path).convert("RGB") 34 35 img = self.transform(img) 36 37 return img, label 38 39 40transform = transforms.Compose([transforms.Resize((256, 256)), transforms.ToTensor()]) 41train_dataset = MyDatasets("/data/mydataset", "train", transform) 42train_dataloader = data.DataLoader(train_dataset, batch_size=32) 43 44for data, labels in train_dataloader: 45 print(data.shape, labels.shape)

投稿2020/08/08 09:24

編集2020/08/11 15:23
tiitoi

総合スコア21956

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

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

oinari03

2020/08/11 13:02

お返事が遅くなってしまい申し訳ありません。 ImageFolderでもできる方法があるのですねありがとうございます。 しかも自動でlabel名が作られるのは驚きです。 しかし、今回はlen、getitemの練習として書こうと思っているので。今後、この知識を使わせてもらいます。 今回はエラーの引数のないことや、ほかのやり方を指摘してくださってありがとうございます。
oinari03

2020/08/11 13:09

頂いたヒントをもとに、もう少し考えてみようと思います。それで改めて質問をしようと思います。ありがとうございます。
oinari03

2020/08/11 13:21

''' # データセット作成 class MyDatasets(data.Dataset): def __init__(self, path=None, key='train', transform=None): self.transform = transform # self.key = key # self.path = path self.data = [] self.lables = [] dataset_root = './animal_dataset/train/' target_label = ["dog","cat"] target_path_list = [] # labelを0/1で付与 for t in target_label: target_dir = os.path.join(dataset_root, t, "*") target_path_list += glob.glob(target_dir) for i in target_path_list: label = os.path.basename(os.path.dirname(i)) if label == "cat": label = 0 elif label == "dog": label = 1 self.labels.append(label) # dataリスト作成 for i in target_path_list: self.data.append(i) ''' ちなみにinitのところのlabelの付与はこのように書きましたが、これをどのようにgetitemで取り出せばいいのか見当がつきません....
tiitoi

2020/08/11 15:23

そのコードでやるのであれば、追記したように修正すればいいのではないでしょうか
oinari03

2020/08/12 02:27

何から何までありがとうございます!! 出力を見ると以下のようになっていました。 """ torch.Size([32, 3, 256, 256]) torch.Size([32]) torch.Size([32, 3, 256, 256]) torch.Size([32]) torch.Size([32, 3, 256, 256]) torch.Size([32]) torch.Size([32, 3, 256, 256]) torch.Size([32]) torch.Size([1, 3, 256, 256]) torch.Size([1]) """ 出力しているのはlabelとdataのshapeのようですが、なぜでしょうか。今後学習する流れで使うような流れでしょうか? ちなみにgetitemのなかでconvertしている意図は何でしょうか? お時間とご都合が合いましたらご享受してくださると幸いです。
tiitoi

2020/08/12 03:40 編集

> 出力しているのはlabelとdataのshapeのようですが、なぜでしょうか。 dataloader でちゃんとミニバッチを返していることを確認するためにデバッグ用に出力しました。 > getitemのなかでconvertしている意図は何でしょうか? 画像の中に1チャンネルや4チャンネルの画像が混じっているとエラーになるため、念のため、RGB に変換しています。
oinari03

2020/08/12 06:30

いろいろ丁寧に教えてくださりありがとうございます。 様々な知識を教えてもらったので、そこから深堀して調査していきたいです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問