2021年9月13日 星期一

機器學習筆記 : 使用 urllib 下載資料集的問題

今天在讀 "精通機器學習" 這本書的第二章時看到作者介紹下載資料集的方法, 他使用 urllib 模組撰寫了一個函式來簡化整個資料集程序, 範例程式碼如下 : 

import os
import tarfile
import urllib      # 應改成 import.urllib.request 

DOWNLOAD_ROOT = "https://raw.githubusercontent.com/ageron/handson-ml2/master/"
HOUSING_PATH = os.path.join("datasets", "housing")
HOUSING_URL = DOWNLOAD_ROOT + "datasets/housing/housing.tgz"

def fetch_housing_data(housing_url=HOUSING_URL, housing_path=HOUSING_PATH):
    os.makedirs(housing_path, exist_ok=True)
    tgz_path = os.path.join(housing_path, "housing.tgz")
    urllib.request.urlretrieve(housing_url, tgz_path)
    housing_tgz = tarfile.open(tgz_path)
    housing_tgz.extractall(path=housing_path)
    housing_tgz.close()

fetch_dataset()

此程式下載的是一份位於 GitHub 上的房屋資訊資料集壓縮檔 housing.tgz, 故需要用到 tarfile 模組進行解壓縮. 其中 DOWNLOAD_ROOT 儲存目標檔案的路徑,  HOUSING_URL 是目標檔案的完整網址, HOUSING_PATH 則是下載後的儲存位置, 此處指定放在程式所在目錄底下的 dataset/housing 子目錄. 

不過我實際測試確出現如下錯誤 (我使用的是 Python 3.7.2) :

>>> %Run urllib_download_dataset.py
Traceback (most recent call last):
  File "D:\test\python\urllib_download_dataset.py", line 17, in <module>
    fetch_housing_data()
  File "D:\test\python\urllib_download_dataset.py", line 12, in fetch_housing_data
    urllib.request.urlretrieve(housing_url, tgz_path)
AttributeError: module 'urllib' has no attribute 'request'   

我找到下面這篇 Stackoverflow 上的討論, 原來是 urllib 匯入方式要改為 import urllib.request (可能是版本問題), urllib 須明確匯入所需要的部分, 而不是匯入根模組 :


"With packages, like this, you sometimes need to explicitly import the piece you want. That way, the urllib module doesn't have to load everything up just because you wanted one small part."
 
我就只是將上面程式的第三行改成 import urllib.request 即可順利執行, 在 dataset/housing 底下找到下載的 housing.tgz 與解壓縮後的 housing.csv 檔 :




完整的程式如下 : 

import os
import tarfile
import urllib.request    

DOWNLOAD_ROOT = "https://raw.githubusercontent.com/ageron/handson-ml2/master/"
HOUSING_PATH = os.path.join("datasets", "housing")
HOUSING_URL = DOWNLOAD_ROOT + "datasets/housing/housing.tgz"

def fetch_housing_data(housing_url=HOUSING_URL, housing_path=HOUSING_PATH):
    os.makedirs(housing_path, exist_ok=True)
    tgz_path = os.path.join(housing_path, "housing.tgz")
    urllib.request.urlretrieve(housing_url, tgz_path)
    housing_tgz = tarfile.open(tgz_path)
    housing_tgz.extractall(path=housing_path)
    housing_tgz.close()

fetch_housing_data()

以後要下載其他資料集只要更改 DOWNLOAD_ROOT 與 HOUSING_URL 即可. 

沒有留言 :