PyTorchではじめるAI開発(書籍)をやってみてつまずいたこと

# はじめに

最近PyTorchの勉強を通して、AIの勉強をすることに力を入れており、
PyTorch本も残すところ以下の本のみとなりました。

https://www.amazon.co.jp/PyTorch%E3%81%A7%E3%81%AF%E3%81%98%E3%82%81%E3%82%8BAI%E9%96%8B%E7%99%BA-%E5%9D%82%E6%9C%AC-%E4%BF%8A%E4%B9%8B/dp/4863543530/ref=sr_1_8?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=Pytorch&qid=1634468474&sr=8-8

こちらの本は2021年6月に発売されていますが、この時代にしては珍しくGoogleColabに対応しておりません。そこで環境構築からコードの準備まですべて行いました。やはりGoogleColabのように実行だけで動かせない箇所があり、本通りにはいかない部分がありましたのでまとめていきたいと思います。


# 環境
- Windows 10
- GPU: GEFORCE GTX 1650 (ノートパソコン)

# 問題

## 1.ffmpegのインストール

**ffmpeg-release-full.zip**をインストールするとありますが、見当たりませんでした。

https://www.gyan.dev/ffmpeg/builds/

から**ffmpeg-4.3.2-essentials_build.zip**をインストールしました。

また、WindowsによってPCが保護されましたというメッセージは特に表示されず、ダブルクリックしても何も変化がおきませんでしたが、コマンドプロンプトで以下のコマンドでコマンド一覧のようなものがでたので問題なさそうでした。

```
$ ffmpeg -h
```

## 2.chapt02-1.pyでfor X, y in data_loaderでエラーになる

```
(py) C:\Users\jinwa\Desktop\PyTorchではじめるAI開発\chap2>python chapt02_1.py
Downloading: "https://download.pytorch.org/models/resnet50-19c8e357.pth" to C:\Users\jinwa/.cache\torch\hub\checkpoints\resnet50-19c8e357.pth
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 97.8M/97.8M [00:12<00:00, 8.00MB/s]
test #0 lr=0.001 weight=0.1
test #0 lr=0.001 weight=0.1
Traceback (most recent call last):
  File "<string>", line 1, in <module>
Traceback (most recent call last):
  File "chapt02_1.py", line 163, in <module>
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\spawn.py", line 105, in spawn_main
    for X, y in data_loader: # 画像を読み込んでtensorにする
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\utils\data\dataloader.py", line 355, in __iter__
    exitcode = _main(fd)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\spawn.py", line 114, in _main
    return self._get_iterator()
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\utils\data\dataloader.py", line 301, in _get_iterator
    prepare(preparation_data)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\spawn.py", line 225, in prepare
    return _MultiProcessingDataLoaderIter(self)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\utils\data\dataloader.py", line 914, in __init__
    _fixup_main_from_path(data['init_main_from_path'])
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\spawn.py", line 277, in _fixup_main_from_path
    run_name="__mp_main__")
    w.start()
  File "C:\Users\jinwa\miniconda3\envs\py\lib\runpy.py", line 263, in run_path
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\process.py", line 112, in start
    pkg_name=pkg_name, script_name=fname)
    self._popen = self._Popen(self)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\runpy.py", line 96, in _run_module_code
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\context.py", line 223, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
    mod_name, mod_spec, pkg_name, script_name)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\context.py", line 322, in _Popen
  File "C:\Users\jinwa\miniconda3\envs\py\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
    return Popen(process_obj)
  File "C:\Users\jinwa\Desktop\PyTorchではじめるAI開発\chap2\chapt02_1.py", line 163, in <module>
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\popen_spawn_win32.py", line 89, in __init__
    for X, y in data_loader: # 画像を読み込んでtensorにする
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\utils\data\dataloader.py", line 355, in __iter__
    reduction.dump(process_obj, to_child)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\reduction.py", line 60, in dump
    return self._get_iterator()
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\utils\data\dataloader.py", line 301, in _get_iterator
    ForkingPickler(file, protocol).dump(obj)
BrokenPipeError: [Errno 32] Broken pipe
    return _MultiProcessingDataLoaderIter(self)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\utils\data\dataloader.py", line 914, in __init__
    w.start()
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\process.py", line 112, in start
    self._popen = self._Popen(self)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\context.py", line 223, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\context.py", line 322, in _Popen
    return Popen(process_obj)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\popen_spawn_win32.py", line 46, in __init__
    prep_data = spawn.get_preparation_data(process_obj._name)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\spawn.py", line 143, in get_preparation_data
    _check_not_importing_main()
  File "C:\Users\jinwa\miniconda3\envs\py\lib\multiprocessing\spawn.py", line 136, in _check_not_importing_main
    is not going to be frozen to produce an executable.''')
RuntimeError:
        An attempt has been made to start a new process before the
        current process has finished its bootstrapping phase.

        This probably means that you are not using fork to start your
        child processes and you have forgotten to use the proper idiom
        in the main module:

            if __name__ == '__main__':
                freeze_support()
                ...

        The "freeze_support()" line can be omitted if the program
        is not going to be frozen to produce an executable.
```

以下の記事を参考にコードを修正します。
[python multiprocessingを使って並列処理を行う](https://mebee.info/2021/03/17/post-22849/)

要は、if __name__ == '__main__'のなかでマルチスレッドを利用するコードを実行してねというもの

コードが公開されていませんので、載せられませんが
def以外のコードを中に入れます。

```
if __name__ == '__main__':
  (関数とグローバル変数(大文字変数)以外を中に入れる
```

## 2.chapt02_2.pyでInput type (torch.cuda.FloatTensor) and weight type (torch.FloatTensor) should be the same

chapt02_2.pyを実行すると以下のようなエラーになります。

```
(py) C:\Users\jinwa\Desktop\PyTorchではじめるAI開発\chap2>python chapt02_2.py
Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Users\jinwa\miniconda3\envs\py\lib\threading.py", line 926, in _bootstrap_inner
    self.run()
  File "C:\Users\jinwa\miniconda3\envs\py\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "chapt02_2.py", line 81, in detect
    batch_result = model(batch_tensor)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
    result = self.forward(*input, **kwargs)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torchvision\models\resnet.py", line 249, in forward
    return self._forward_impl(x)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torchvision\models\resnet.py", line 232, in _forward_impl
    x = self.conv1(x)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
    result = self.forward(*input, **kwargs)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\nn\modules\conv.py", line 399, in forward
    return self._conv_forward(input, self.weight, self.bias)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\nn\modules\conv.py", line 396, in _conv_forward
    self.padding, self.dilation, self.groups)
RuntimeError: Input type (torch.cuda.FloatTensor) and weight type (torch.FloatTensor) should be the same
```

このエラーが発生するとモデルが読み込めていないため、認識の結果が表示されません。

以下の記事を参考にコードに1行追加します。
[RuntimeError: Input type (torch.cuda.FloatTensor) and weight type (torch.FloatTensor) should be the same](https://discuss.pytorch.org/t/runtimeerror-input-type-torch-cuda-floattensor-and-weight-type-torch-floattensor-should-be-the-same/21782)

```chapt01_2.py

# 保存しておいたモデルを読み込む
model = models.resnet50(pretrained=False)
model.fc = nn.Linear(2048, 2)
model.load_state_dict(torch.load('chapt02-model1.pth', map_location=torch.device(USE_DEVICE)))
model.cuda() # 追加
# モデルを推論用に設定する
model.eval()
```

## chapt04_1でno module seaborn

書籍にはないですが、**seaborn**のインストールが必要です。
Anacondaのプロンプトで以下のコマンドでインストールします。

```
$ pip install seaborn
```

## chapt04_02で入力の形状でエラー

```
Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Users\jinwa\miniconda3\envs\py\lib\threading.py", line 926, in _bootstrap_inner
    self.run()
  File "C:\Users\jinwa\miniconda3\envs\py\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "chapt04_2.py", line 64, in detect
    results = model(img_tensor, size=640)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
    result = self.forward(*input, **kwargs)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\autograd\grad_mode.py", line 27, in decorate_context
    return func(*args, **kwargs)
  File "C:\Users\jinwa/.cache\torch\hub\ultralytics_yolov5_master\models\common.py", line 317, in forward
    return self.model(imgs.to(p.device).type_as(p), augment, profile)  # inference
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
    result = self.forward(*input, **kwargs)
  File "C:\Users\jinwa/.cache\torch\hub\ultralytics_yolov5_master\models\yolo.py", line 126, in forward
    return self._forward_once(x, profile, visualize)  # single-scale inference, train
  File "C:\Users\jinwa/.cache\torch\hub\ultralytics_yolov5_master\models\yolo.py", line 149, in _forward_once
    x = m(x)  # run
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
    result = self.forward(*input, **kwargs)
  File "C:\Users\jinwa/.cache\torch\hub\ultralytics_yolov5_master\models\common.py", line 48, in forward_fuse
    return self.act(self.conv(x))
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\nn\modules\module.py", line 889, in _call_impl
    result = self.forward(*input, **kwargs)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\nn\modules\conv.py", line 399, in forward
    return self._conv_forward(input, self.weight, self.bias)
  File "C:\Users\jinwa\miniconda3\envs\py\lib\site-packages\torch\nn\modules\conv.py", line 396, in _conv_forward
    self.padding, self.dilation, self.groups)
RuntimeError: Given groups=1, weight of size [32, 3, 6, 6], expected input[1, 720, 1280, 3] to have 3 channels, but got 720 channels instea
```

メールで問い合わせ中
回答が返ってきたが、思うように動かずそれ以降のコードは動かせていません。

## chapt05_1でcoco datasetが解凍できない

Laplusでなぜか解凍ができなかった。

![bandicam 2021-10-18 16-22-29-790.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/a15093c1-90fe-dfc5-9f87-39689b237a76.jpeg)

7zipなら解凍できた。

![bandicam 2021-10-18 16-29-39-448.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/acac8bc4-51d8-bbd3-ee1f-9c3cb9353150.jpeg)



# おわりに
Colabでしたら、実行だけで動きますが今回はAnaconda環境なのでやはり書籍通りにうまくいきませんでした。
できたらColab対応を望みますが、コードのダウンロードにもパスワードが必要なので難しそうですね。

こうなると勉強する人も少なくなるのかなと思いつつ、「はじめての」人がうやっても挫折しないようにこれからもまとめていきたいと思います。

私が挫折せずに果たしてできるのか。心配です。


# 参考
- [python multiprocessingを使って並列処理を行う](https://mebee.info/2021/03/17/post-22849/)
- [RuntimeError: Input type (torch.cuda.FloatTensor) and weight type (torch.FloatTensor) should be the same](https://discuss.pytorch.org/t/runtimeerror-input-type-torch-cuda-floattensor-and-weight-type-torch-floattensor-should-be-the-same/21782)