393 lines
11 KiB
Plaintext
393 lines
11 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Deep Learning Models -- A collection of various deep learning architectures, models, and tips for TensorFlow and PyTorch in Jupyter Notebooks.\n",
|
|
"- Author: Sebastian Raschka\n",
|
|
"- GitHub Repository: https://github.com/rasbt/deeplearning-models"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Sebastian Raschka \n",
|
|
"\n",
|
|
"CPython 3.7.1\n",
|
|
"IPython 7.2.0\n",
|
|
"\n",
|
|
"torch 1.0.0\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%load_ext watermark\n",
|
|
"%watermark -a 'Sebastian Raschka' -v -p torch"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Model Zoo -- Using PyTorch Dataset Loading Utilities for Custom Datasets (CSV files converted to HDF5)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"This notebook provides an example for how to load a dataset from an HDF5 file created from a CSV file, using PyTorch's data loading utilities. For a more in-depth discussion, please see the official\n",
|
|
"\n",
|
|
"- [Data Loading and Processing Tutorial](http://pytorch.org/tutorials/beginner/data_loading_tutorial.html)\n",
|
|
"- [torch.utils.data](http://pytorch.org/docs/master/data.html) API documentation\n",
|
|
"\n",
|
|
"An Hierarchical Data Format (HDF) is a convenient way that allows quick access to data instances during minibatch learning if a dataset is too large to fit into memory. The approach outlined in this notebook uses uses the common [HDF5](https://support.hdfgroup.org/HDF5/) format and should be accessible to any programming language or tool with an HDF5 API.\n",
|
|
"\n",
|
|
"**In this example, we are going to use the Iris dataset for illustrative purposes. Let's pretend it's our large training dataset that doesn't fit into memory**.\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Imports"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import pandas as pd\n",
|
|
"import numpy as np\n",
|
|
"import h5py\n",
|
|
"import torch\n",
|
|
"from torch.utils.data import Dataset\n",
|
|
"from torch.utils.data import DataLoader"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Converting a CSV file to HDF5"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"In this first step, we are going to process a CSV file (here, Iris) into an HDF5 database:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# suppose this is a large CSV that does not \n",
|
|
"# fit into memory:\n",
|
|
"csv_path = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'\n",
|
|
"\n",
|
|
"# Get number of lines in the CSV file if it's on your hard drive:\n",
|
|
"#num_lines = subprocess.check_output(['wc', '-l', in_csv])\n",
|
|
"#num_lines = int(nlines.split()[0]) \n",
|
|
"num_lines = 150\n",
|
|
"num_features = 4\n",
|
|
"\n",
|
|
"class_dict = {'Iris-setosa': 0,\n",
|
|
" 'Iris-versicolor': 1,\n",
|
|
" 'Iris-virginica': 2}\n",
|
|
"\n",
|
|
"# use 10,000 or 100,000 or so for large files\n",
|
|
"chunksize = 10\n",
|
|
"\n",
|
|
"# this is your HDF5 database:\n",
|
|
"with h5py.File('iris.h5', 'w') as h5f:\n",
|
|
" \n",
|
|
" # use num_features-1 if the csv file has a column header\n",
|
|
" dset1 = h5f.create_dataset('features',\n",
|
|
" shape=(num_lines, num_features),\n",
|
|
" compression=None,\n",
|
|
" dtype='float32')\n",
|
|
" dset2 = h5f.create_dataset('labels',\n",
|
|
" shape=(num_lines,),\n",
|
|
" compression=None,\n",
|
|
" dtype='int32')\n",
|
|
"\n",
|
|
" # change range argument from 0 -> 1 if your csv file contains a column header\n",
|
|
" for i in range(0, num_lines, chunksize): \n",
|
|
"\n",
|
|
" df = pd.read_csv(csv_path, \n",
|
|
" header=None, # no header, define column header manually later\n",
|
|
" nrows=chunksize, # number of rows to read at each iteration\n",
|
|
" skiprows=i) # skip rows that were already read\n",
|
|
" \n",
|
|
" df[4] = df[4].map(class_dict)\n",
|
|
"\n",
|
|
" features = df.values[:, :4]\n",
|
|
" labels = df.values[:, -1]\n",
|
|
" \n",
|
|
" # use i-1 and i-1+10 if csv file has a column header\n",
|
|
" dset1[i:i+10, :] = features\n",
|
|
" dset2[i:i+10] = labels[0]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"After creating the database, let's double-check that everything works correctly:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"(150, 4)\n",
|
|
"(150,)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"with h5py.File('iris.h5', 'r') as h5f:\n",
|
|
" print(h5f['features'].shape)\n",
|
|
" print(h5f['labels'].shape)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Features of entry no. 99: [5.7 2.8 4.1 1.3]\n",
|
|
"Class label of entry no. 99: 1\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"with h5py.File('iris.h5', 'r') as h5f:\n",
|
|
" print('Features of entry no. 99:', h5f['features'][99])\n",
|
|
" print('Class label of entry no. 99:', h5f['labels'][99])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Implementing a Custom Dataset Class"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Now, we implement a custom `Dataset` for reading the training examples. The `__getitem__` method will\n",
|
|
"\n",
|
|
"1. read a single training example from HDF5 based on an `index` (more on batching later)\n",
|
|
"2. return a single training example and it's corresponding label\n",
|
|
"\n",
|
|
"Note that we will keep an open connection to the database for efficiency via `self.h5f = h5py.File(h5_path, 'r')` -- you may want to close it when you are done (more on this later)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Hdf5Dataset(Dataset):\n",
|
|
" \"\"\"Custom Dataset for loading entries from HDF5 databases\"\"\"\n",
|
|
"\n",
|
|
" def __init__(self, h5_path, transform=None):\n",
|
|
" \n",
|
|
" self.h5f = h5py.File(h5_path, 'r')\n",
|
|
" self.num_entries = self.h5f['labels'].shape[0]\n",
|
|
" self.transform = transform\n",
|
|
"\n",
|
|
" def __getitem__(self, index):\n",
|
|
" \n",
|
|
" features = self.h5f['features'][index]\n",
|
|
" label = self.h5f['labels'][index]\n",
|
|
" if self.transform is not None:\n",
|
|
" features = self.transform(features)\n",
|
|
" return features, label\n",
|
|
"\n",
|
|
" def __len__(self):\n",
|
|
" return self.num_entries"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Now that we have created our custom Dataset class, we can initialize a Dataset instance for the training examples using the 'iris.h5' database file. Then, we initialize a `DataLoader` that allows us to read from the dataset."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"train_dataset = Hdf5Dataset(h5_path='iris.h5',\n",
|
|
" transform=None)\n",
|
|
"\n",
|
|
"train_loader = DataLoader(dataset=train_dataset,\n",
|
|
" batch_size=50,\n",
|
|
" shuffle=True,\n",
|
|
" num_workers=4) "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"That's it! Now we can iterate over an epoch using the train_loader as an iterator and use the features and labels from the training dataset for model training as shown in the next section"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Iterating Through the Custom Dataset"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Epoch: 1 | Batch index: 0 | Batch size: 50\n",
|
|
"Epoch: 1 | Batch index: 1 | Batch size: 50\n",
|
|
"Epoch: 1 | Batch index: 2 | Batch size: 50\n",
|
|
"Epoch: 2 | Batch index: 0 | Batch size: 50\n",
|
|
"Epoch: 2 | Batch index: 1 | Batch size: 50\n",
|
|
"Epoch: 2 | Batch index: 2 | Batch size: 50\n",
|
|
"Epoch: 3 | Batch index: 0 | Batch size: 50\n",
|
|
"Epoch: 3 | Batch index: 1 | Batch size: 50\n",
|
|
"Epoch: 3 | Batch index: 2 | Batch size: 50\n",
|
|
"Epoch: 4 | Batch index: 0 | Batch size: 50\n",
|
|
"Epoch: 4 | Batch index: 1 | Batch size: 50\n",
|
|
"Epoch: 4 | Batch index: 2 | Batch size: 50\n",
|
|
"Epoch: 5 | Batch index: 0 | Batch size: 50\n",
|
|
"Epoch: 5 | Batch index: 1 | Batch size: 50\n",
|
|
"Epoch: 5 | Batch index: 2 | Batch size: 50\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
|
|
"torch.manual_seed(0)\n",
|
|
"\n",
|
|
"num_epochs = 5\n",
|
|
"for epoch in range(num_epochs):\n",
|
|
"\n",
|
|
" for batch_idx, (x, y) in enumerate(train_loader):\n",
|
|
" \n",
|
|
" print('Epoch:', epoch+1, end='')\n",
|
|
" print(' | Batch index:', batch_idx, end='')\n",
|
|
" print(' | Batch size:', y.size()[0])\n",
|
|
" \n",
|
|
" x = x.to(device)\n",
|
|
" y = y.to(device)\n",
|
|
"\n",
|
|
" # do model training on x and y here"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"**Remember that we kept an open connection to the HDF5 database in the `Hdf5Dataset` (via `self.h5f = h5py.File(h5_path, 'r')`). Once we are done, we may want to close this connection:**"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"train_dataset.h5f.close()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"torch 1.0.0\n",
|
|
"pandas 0.23.4\n",
|
|
"numpy 1.15.4\n",
|
|
"h5py 2.8.0\n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%watermark -iv"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.7.1"
|
|
},
|
|
"toc": {
|
|
"nav_menu": {},
|
|
"number_sections": true,
|
|
"sideBar": true,
|
|
"skip_h1_title": false,
|
|
"title_cell": "Table of Contents",
|
|
"title_sidebar": "Contents",
|
|
"toc_cell": false,
|
|
"toc_position": {},
|
|
"toc_section_display": true,
|
|
"toc_window_display": false
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|