物理のバス停 by salt22g

とある物理学見習いの備忘録。

pytorch, Docker…proxy環境下でのfile download

最近、Linuxサーバーにsshで接続し、その中でDockerを走らせてpytorchを使っている筆者です。
(何を言ってるのか分からねぇと思うが…)

proxy環境下での開発環境整備やDocker imageの作成で苦戦したのですが徐々に理解が進んでいます。
その辺りはいずれ記事にしたいと思っています。

pytorchのパラメータファイル自動ダウンロード…

今流行りの機械学習
pythonを使ったフレームワークの中の一つにpytorchがあります。

pytorch.org

研究室で導入しているので「私も勉強しなくては!」と思い、公式サイトのtutorialをやってみました。

最近の機械学習フレームワークはめちゃくちゃ賢い。
目的にあった学習済みのパラメータファイルをネットからダウンロードして使えるようになっています。
しかし、proxy環境で動くDockerの中でダウンロードが動かず
以下に詳細と解決策を。

環境

NAME="Ubuntu"
VERSION="16.04.6 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.6 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial

Docker image: nvcr.io/nvidia/pytorch:19.08-py3
以下のサイトからgit cloneしたやつです。
github.com


proxy環境
salt22g.hatenablog.jp
この記事にある設定を使っています。
proxy環境下のDockerの中でもwget等は問題なく使えています。

問題発生

transfer_learning_tutorial.pyという手法を試してみました。
pytorchによる画像分類のtutorialです。
github.com

このコードの253行目
https://github.com/pytorch/tutorials/blob/f557ee0addc24900929bafd4ceff2fc4c3f47072/beginner_source/transfer_learning_tutorial.py

model_ft = models.resnet18(pretrained=True)

この行で学習済みファイルを読みに行きます。
今回のコードでは

Downloading: "https://download.pytorch.org/models/resnet18-5c106cde.pth" to /root/.cache/torch/checkpoints/resnet18-5c106cde.pth

が実行されますがerrorが…

Traceback (most recent call last):
  File "/opt/conda/lib/python3.6/urllib/request.py", line 1318, in do_open
    encode_chunked=req.has_header('Transfer-encoding'))
  File "/opt/conda/lib/python3.6/http/client.py", line 1254, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/opt/conda/lib/python3.6/http/client.py", line 1300, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/opt/conda/lib/python3.6/http/client.py", line 1249, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/opt/conda/lib/python3.6/http/client.py", line 1036, in _send_output
    self.send(msg)
  File "/opt/conda/lib/python3.6/http/client.py", line 974, in send
    self.connect()
  File "/opt/conda/lib/python3.6/http/client.py", line 1407, in connect
    super().connect()
  File "/opt/conda/lib/python3.6/http/client.py", line 946, in connect
    (self.host,self.port), self.timeout, self.source_address)
  File "/opt/conda/lib/python3.6/socket.py", line 704, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "/opt/conda/lib/python3.6/socket.py", line 745, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -3] Temporary failure in name resolution

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "transfer_learning_tutorial_org.py", line 254, in <module>
    model_ft = models.resnet18(pretrained=True)
  File "/opt/conda/lib/python3.6/site-packages/torchvision/models/resnet.py", line 231, in resnet18
    **kwargs)
  File "/opt/conda/lib/python3.6/site-packages/torchvision/models/resnet.py", line 217, in _resnet
    progress=progress)
  File "/opt/conda/lib/python3.6/site-packages/torch/hub.py", line 457, in load_state_dict_from_url
    _download_url_to_file(url, cached_file, hash_prefix, progress=progress)
  File "/opt/conda/lib/python3.6/site-packages/torch/hub.py", line 372, in _download_url_to_file
    u = urlopen(url)
  File "/opt/conda/lib/python3.6/urllib/request.py", line 223, in urlopen
    return opener.open(url, data, timeout)
  File "/opt/conda/lib/python3.6/urllib/request.py", line 526, in open
    response = self._open(req, data)
  File "/opt/conda/lib/python3.6/urllib/request.py", line 544, in _open
    '_open', req)
  File "/opt/conda/lib/python3.6/urllib/request.py", line 504, in _call_chain
    result = func(*args)
  File "/opt/conda/lib/python3.6/urllib/request.py", line 1361, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "/opt/conda/lib/python3.6/urllib/request.py", line 1320, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [Errno -3] Temporary failure in name resolution>

解決法

どうやらpythonのrequest.pyとやらがproxyの設定を読み込めていない模様。

qiita.com

こちらの記事によると環境変数を設定すれば良いとのこと。

export HTTP_PROXY="http://${USERNAME}:${PASSWORD}@${PROXY_HOST}:${PROXY_PORT}"

筆者もこの設定したはずなんだけど動かない。
そこでもう一つの解決法を試しました。
pythonのプログラムにこちらを追加。

import os
os.environ["http_proxy"] = "http://user:pass@server:port"
os.environ["https_proxy"] = "http://user:pass@server:port"

すると問題なくダウンロードが行われ学習が開始されました。