Skip to content

Instantly share code, notes, and snippets.

@arthurmensch
Created January 24, 2017 15:04
Show Gist options
  • Save arthurmensch/5212e45010573cdd200e7bf5de710412 to your computer and use it in GitHub Desktop.
Save arthurmensch/5212e45010573cdd200e7bf5de710412 to your computer and use it in GitHub Desktop.
MongoDB tutorial + sacred examples
# Author: Arthur Mensch
# License: BSD
import os
import time
import matplotlib.pyplot as plt
from modl.feature_extraction.image import LazyCleanPatchExtractor
from modl.image import ImageDictFact
from sacred import Experiment
from modl.datasets.image import load_image
from modl.plotting.image import plot_patches
from sacred.observers import MongoObserver
"""Install master of modl"""
decompose_ex = Experiment('decompose_images')
observer = MongoObserver.create(url='localhost', db_name='experiments',
port=27017)
decompose_ex.observers.append(observer)
@decompose_ex.config
def config():
batch_size = 400
learning_rate = 0.92
reduction = 10
alpha = 0.08
n_epochs = 10
n_components = 50
test_size = 4000
max_patches = 10000
patch_size = (16, 16)
n_threads = 3
verbose = 20
method = 'gram'
setting = 'dictionary learning'
source = 'lisboa'
gray = False
scale = 1
class DictionaryScorer:
def __init__(self, test_data):
self.start_time = time.clock()
self.test_data = test_data
self.test_time = 0
self.time = []
self.score = []
self.iter = []
@decompose_ex.capture
def __call__(self, dict_fact, _run):
test_time = time.clock()
score = dict_fact.score(self.test_data)
self.test_time += time.clock() - test_time
this_time = time.clock() - self.start_time - self.test_time
self.time.append(this_time)
self.score.append(score)
self.iter.append(dict_fact.n_iter_)
_run.info['score'] = self.score
_run.info['time'] = self.time
_run.info['iter'] = self.iter
@decompose_ex.automain
def decompose_run(batch_size,
learning_rate,
reduction,
n_components,
n_epochs,
patch_size,
test_size,
alpha,
setting,
n_threads,
verbose,
max_patches,
method,
source,
scale, gray,
_run,
_seed,
):
print('Loading data')
image = load_image(source, scale=scale, gray=gray)
print('Done')
width, height, n_channel = image.shape
patch_extractor = LazyCleanPatchExtractor(patch_size=patch_size,
max_patches=test_size,
random_state=_seed)
test_data = patch_extractor.transform(image[:, :height // 2, :])
cb = DictionaryScorer(test_data)
dict_fact = ImageDictFact(method=method,
setting=setting,
alpha=alpha,
n_epochs=n_epochs,
random_state=_seed,
n_components=n_components,
learning_rate=learning_rate,
max_patches=max_patches,
batch_size=batch_size,
patch_size=patch_size,
reduction=reduction,
callback=cb,
verbose=verbose,
n_threads=n_threads,
)
dict_fact.fit(image[:, height // 2:, :])
score = dict_fact.score(test_data)
_run.info['final_score'] = score
fig = plt.figure()
patches = dict_fact.components_
plot_patches(fig, patches)
fig.suptitle('Dictionary components')
plt.savefig('components.png')
plt.close(fig)
_run.add_artifact('components.png')
os.unlink('components.png')
fig, ax = plt.subplots(1, 1)
ax.plot(cb.time, cb.score, marker='o')
ax.legend()
ax.set_xscale('log')
ax.set_xlabel('Time (s)')
ax.set_ylabel('Test objective value')
plt.savefig('training_curve.png')
plt.close(fig)
_run.add_artifact('training_curve.png')
os.unlink('training_curve.png')
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# MongoDB + Pymongo tutorial\n",
"\n",
"How to use it to crawl experimental data ?\n",
"\n",
"- Manual approach\n",
"- Using ```sacred```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install\n",
"\n",
"```bash\n",
"sudo apt install mongodb\n",
"sudo servicectl start mongodb\n",
"pip install pymongo\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Basic introduction\n",
"\n",
"### Connection"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Server > Database > Collection (~ Table in MySQL)"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Deleted 7 records\n"
]
}
],
"source": [
"import pymongo\n",
"from pymongo import MongoClient\n",
"from collections import OrderedDict\n",
"\n",
"client = MongoClient('localhost', 27017, document_class=OrderedDict)\n",
"db = client['basic']\n",
"collection = db['basic']\n",
"# Clear collection\n",
"result = collection.delete_many({})\n",
"print('Deleted %s records' % result.deleted_count)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Insertion"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Insert a first element"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import datetime\n",
"\n",
"post = {\"author\": \"Elvis\",\n",
" \"text\": \"Learning topos from data in the wild\",\n",
" \"tags\": [\"topos\", \"wild\", 'data'],\n",
" \"date\": datetime.datetime.utcnow()}\n",
"\n",
"result = collection.insert_one(post)\n",
"\n",
"post = {\"author\": \"Arthur\",\n",
" \"text\": \"Running FSL on a whole bunch of data\",\n",
" \"tags\": [\"boring\", \"fsl\"],\n",
" \"date\": datetime.datetime.utcnow()}\n",
"\n",
"result = collection.insert_one(post)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Ids\n",
"\n",
"Each inserted element is given an id, that can be used for look-up"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"58875aee46695643db731b8c\n"
]
},
{
"data": {
"text/plain": [
"OrderedDict([('_id', ObjectId('58875aee46695643db731b8c')),\n",
" ('author', 'Arthur'),\n",
" ('text', 'Running FSL on a whole bunch of data'),\n",
" ('tags', ['boring', 'fsl']),\n",
" ('date', datetime.datetime(2017, 1, 24, 13, 47, 26, 440000))])"
]
},
"execution_count": 61,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"object_id = result.inserted_id\n",
"print(object_id)\n",
"collection.find_one(object_id)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Queries\n",
"\n",
"#### Basic look-up: return cursor"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Running FSL on a whole bunch of data\n",
"Running FSL on a whole bunch of data\n"
]
}
],
"source": [
"cursor = collection.find({'author': 'Arthur'})\n",
"for result in cursor:\n",
" print(result['text'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### More complex filtering operations"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Tag: boring\n",
"- Running FSL on a whole bunch of data\n",
"- Running FSL on a whole bunch of data\n",
"Tag: fsl, topos\n",
"- Learning topos from data in the wild\n",
"- Running FSL on a whole bunch of data\n",
"- Learning topos from data in the wild\n",
"- Running FSL on a whole bunch of data\n"
]
}
],
"source": [
"print('Tag: boring')\n",
"cursor = collection.find({'tags': {\"$in\": [\"boring\"]}})\n",
"for result in cursor:\n",
" print(\"- %s\" % result['text'])\n",
"print('Tag: fsl, topos')\n",
"cursor = collection.find({'tags': {\"$in\": [\"fsl\", \"topos\"]}})\n",
"for result in cursor:\n",
" print(\"- %s\" % result['text'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Without structure queries\n",
"\n",
"#### Extending fields without problems"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"post = {\"author\": \"Arthur\",\n",
" \"text\": \"Now is time to wake up\",\n",
" \"title\": \"Stay awake\",\n",
" \"tags\": [\"meeting\", \"tuesday\"],\n",
" \"date\": datetime.datetime.utcnow()}\n",
"\n",
"result = collection.insert_one(post)"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Now is time to wake up\n"
]
}
],
"source": [
"result = collection.find_one({'title': \"Stay awake\"})\n",
"print(result['text'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Filter on existence"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Title exists for:\n",
"- Now is time to wake up\n",
"Title does not exists for:\n",
"- Learning topos from data in the wild\n",
"- Running FSL on a whole bunch of data\n",
"- Learning topos from data in the wild\n",
"- Running FSL on a whole bunch of data\n",
"Post has at least three tags:\n",
"- Learning topos from data in the wild\n",
"- Learning topos from data in the wild\n"
]
}
],
"source": [
"print('Title exists for:')\n",
"results = collection.find({\"title\": {\"$exists\": True}})\n",
"for result in results:\n",
" print(\"- %s\" % result['text'])\n",
" \n",
"print('Title does not exists for:')\n",
"results = collection.find({\"title\": {\"$exists\": False}})\n",
"for result in results:\n",
" print(\"- %s\" % result['text'])\n",
" \n",
"print('Post has at least three tags:')\n",
"results = collection.find({\"tags.2\": {\"$exists\": True}})\n",
"for result in results:\n",
" print(\"- %s\" % result['text'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Filter on date, on equality, inequality : https://docs.mongodb.com"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aggregation pipeline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Sorting"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"- Running FSL on a whole bunch of data, 2017-01-24 13:28:40.156000\n",
"- Learning topos from data in the wild, 2017-01-24 13:28:40.155000\n"
]
}
],
"source": [
"results = collection.find({\"tags\": {\"$in\": ['topos', 'fsl']}}).sort('date',pymongo.DESCENDING)\n",
"for result in results:\n",
" print(\"- %s, %s\" % (result['text'], result['date']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's add a few more posts to the collection"
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"posts = [{\"author\": \"Elvis\",\n",
" \"text\": \"Learning saddle-point to make more money\",\n",
" \"tags\": [\"money\", \"saddle\", \"math\"],\n",
" \"date\": datetime.datetime.utcnow()},\n",
" {\"author\": \"DeepPoker\",\n",
" \"text\": \"Playing poker online using conv-nets\",\n",
" \"tags\": [\"deep\", \"money\", \"math\"],\n",
" \"date\": datetime.datetime.utcnow()},\n",
" {\"author\": \"Google\",\n",
" \"text\": \"Making YouTube better with deep learning\",\n",
" \"tags\": [\"deep\", \"money\", \"math\"],\n",
" \"date\": datetime.datetime.utcnow()},\n",
" {\"author\": \"Facebook\",\n",
" \"text\": \"Advertising better shoes with deep learning\",\n",
" \"tags\": [\"deep\", \"money\", \"math\"],\n",
" \"date\": datetime.datetime.utcnow()},\n",
" ]\n",
"\n",
"result = collection.insert_many(posts)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Now for the powerful part"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Tag math: 4 count. Authors: ['Facebook', 'Google', 'DeepPoker', 'Elvis']\n",
"Tag money: 4 count. Authors: ['Facebook', 'Google', 'DeepPoker', 'Elvis']\n",
"Tag deep: 3 count. Authors: ['Facebook', 'Google', 'DeepPoker']\n",
"Tag saddle: 1 count. Authors: ['Elvis']\n"
]
}
],
"source": [
"pipeline = [{\"$match\": {\"tags\": {\"$in\": [\"math\"]}}},\n",
" {\"$unwind\": \"$tags\"},\n",
" {\"$group\": {\"_id\": \"$tags\", \"count\": {\"$sum\": 1}, \"authors\": {\"$addToSet\": '$author'}}},\n",
" {\"$sort\": OrderedDict([(\"count\",pymongo.DESCENDING), (\"_id\",pymongo.ASCENDING)])}\n",
" ]\n",
"results = collection.aggregate(pipeline)\n",
"for result in results:\n",
" print(\"Tag %s: %i count. Authors: %s\" % (result['_id'], result['count'], result['authors']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Let's decompose the pipeline"
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Text: Learning saddle-point to make more money. Tags: ['money', 'saddle', 'math']. Author: Elvis \n",
"Text: Playing poker online using conv-nets. Tags: ['deep', 'money', 'math']. Author: DeepPoker \n",
"Text: Making YouTube better with deep learning. Tags: ['deep', 'money', 'math']. Author: Google \n",
"Text: Advertising better shoes with deep learning. Tags: ['deep', 'money', 'math']. Author: Facebook \n"
]
}
],
"source": [
"pipeline = [{\"$match\": {\"tags\": {\"$in\": [\"math\"]}}}]\n",
"results = collection.aggregate(pipeline)\n",
"for result in results:\n",
" print(\"Text: %s. Tags: %s. Author: %s \" % (result['text'], result['tags'], result['author']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Unwind tags"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Text: Learning saddle-point to make more money. Tags: money. Author: Elvis \n",
"Text: Learning saddle-point to make more money. Tags: saddle. Author: Elvis \n",
"Text: Learning saddle-point to make more money. Tags: math. Author: Elvis \n",
"Text: Playing poker online using conv-nets. Tags: deep. Author: DeepPoker \n",
"Text: Playing poker online using conv-nets. Tags: money. Author: DeepPoker \n",
"Text: Playing poker online using conv-nets. Tags: math. Author: DeepPoker \n",
"Text: Making YouTube better with deep learning. Tags: deep. Author: Google \n",
"Text: Making YouTube better with deep learning. Tags: money. Author: Google \n",
"Text: Making YouTube better with deep learning. Tags: math. Author: Google \n",
"Text: Advertising better shoes with deep learning. Tags: deep. Author: Facebook \n",
"Text: Advertising better shoes with deep learning. Tags: money. Author: Facebook \n",
"Text: Advertising better shoes with deep learning. Tags: math. Author: Facebook \n"
]
}
],
"source": [
"pipeline = [{\"$match\": {\"tags\": {\"$in\": [\"math\"]}}},\n",
" {\"$unwind\": \"$tags\"}]\n",
"results = collection.aggregate(pipeline)\n",
"for result in results:\n",
" print(\"Text: %s. Tags: %s. Author: %s \" % (result['text'], result['tags'], result['author']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Group by tag"
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Tag: deep. Content OrderedDict([('_id', 'deep')])\n",
"Tag: math. Content OrderedDict([('_id', 'math')])\n",
"Tag: saddle. Content OrderedDict([('_id', 'saddle')])\n",
"Tag: money. Content OrderedDict([('_id', 'money')])\n"
]
}
],
"source": [
"pipeline = [{\"$match\": {\"tags\": {\"$in\": [\"math\"]}}},\n",
" {\"$unwind\": \"$tags\"},\n",
" {\"$group\": {\"_id\": \"$tags\"}}]\n",
"results = collection.aggregate(pipeline)\n",
"for result in results:\n",
" print(\"Tag: %s. Content %s\" % (result['_id'], result))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Compute group fields"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Tag deep: 3 count. Authors: ['Facebook', 'Google', 'DeepPoker']\n",
"Tag math: 4 count. Authors: ['Facebook', 'Google', 'DeepPoker', 'Elvis']\n",
"Tag saddle: 1 count. Authors: ['Elvis']\n",
"Tag money: 4 count. Authors: ['Facebook', 'Google', 'DeepPoker', 'Elvis']\n"
]
}
],
"source": [
"pipeline = [{\"$match\": {\"tags\": {\"$in\": [\"math\"]}}},\n",
" {\"$unwind\": \"$tags\"},\n",
" {\"$group\": {\"_id\": \"$tags\", \"count\": {\"$sum\": 1}, \"authors\": {\"$addToSet\": '$author'}}},\n",
" ]\n",
"results = collection.aggregate(pipeline)\n",
"for result in results:\n",
" print(\"Tag %s: %i count. Authors: %s\" % (result['_id'], result['count'], result['authors']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### And sort"
]
},
{
"cell_type": "code",
"execution_count": 77,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Tag math: 4 count. Authors: ['Facebook', 'Google', 'DeepPoker', 'Elvis']\n",
"Tag money: 4 count. Authors: ['Facebook', 'Google', 'DeepPoker', 'Elvis']\n",
"Tag deep: 3 count. Authors: ['Facebook', 'Google', 'DeepPoker']\n",
"Tag saddle: 1 count. Authors: ['Elvis']\n"
]
}
],
"source": [
"pipeline = [{\"$match\": {\"tags\": {\"$in\": [\"math\"]}}},\n",
" {\"$unwind\": \"$tags\"},\n",
" {\"$group\": {\"_id\": \"$tags\", \"count\": {\"$sum\": 1}, \"authors\": {\"$addToSet\": '$author'}}},\n",
" {\"$sort\": OrderedDict([(\"count\",pymongo.DESCENDING), (\"_id\",pymongo.ASCENDING)])}\n",
" ]\n",
"results = collection.aggregate(pipeline)\n",
"for result in results:\n",
" print(\"Tag %s: %i count. Authors: %s\" % (result['_id'], result['count'], result['authors']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### More information on aggregation\n",
"\n",
"https://docs.mongodb.com/manual/reference/"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Using sacred + mongodb in experiments"
]
},
{
"cell_type": "code",
"execution_count": 79,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import pymongo\n",
"from pymongo import MongoClient\n",
"from collections import OrderedDict\n",
"\n",
"client = MongoClient('localhost', 27017, document_class=OrderedDict)\n",
"db = client['experiments']\n",
"collection = db['default.runs']"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO - decompose_images - Running command 'decompose_run'\n",
"INFO - decompose_images - Started\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading data\n",
"Done\n",
"Preparing patch extraction\n",
"Fitting dictionary\n",
"Epoch 1\n",
"Iteration 0\n",
"Iteration 400\n",
"Iteration 800\n",
"Iteration 1200\n",
"Iteration 1600\n",
"Iteration 2000\n",
"Iteration 2400\n",
"Iteration 2800\n",
"Iteration 4000\n",
"Iteration 5200\n",
"Iteration 7200\n",
"Iteration 9600\n",
"Epoch 2\n",
"Shuffling dataset\n",
"Iteration 12800\n",
"Iteration 17200\n",
"Epoch 3\n",
"Shuffling dataset\n",
"Iteration 23200\n",
"Epoch 4\n",
"Shuffling dataset\n",
"Iteration 31200\n",
"Epoch 5\n",
"Shuffling dataset\n",
"Iteration 41600\n",
"Epoch 6\n",
"Shuffling dataset\n",
"Iteration 55600\n",
"Epoch 7\n",
"Shuffling dataset\n",
"Epoch 8\n",
"Shuffling dataset\n",
"Iteration 74400\n",
"Epoch 9\n",
"Shuffling dataset\n",
"Epoch 10\n",
"Shuffling dataset\n",
"Iteration 99600\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/opt/miniconda3/lib/python3.5/site-packages/matplotlib/axes/_axes.py:545: UserWarning: No labelled objects found. Use label='...' kwarg on individual plots.\n",
" warnings.warn(\"No labelled objects found. \"\n",
"INFO - decompose_images - Completed after 0:00:15\n",
"INFO - decompose_images - Running command 'decompose_run'\n",
"INFO - decompose_images - Started\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading data\n",
"Done\n",
"Preparing patch extraction\n",
"Fitting dictionary\n",
"Epoch 1\n",
"Iteration 0\n",
"Iteration 400\n",
"Iteration 800\n",
"Iteration 1200\n",
"Iteration 1600\n",
"Iteration 2000\n",
"Iteration 2400\n",
"Iteration 2800\n",
"Iteration 4000\n",
"Iteration 5200\n",
"Iteration 7200\n",
"Iteration 9600\n",
"Epoch 2\n",
"Shuffling dataset\n",
"Iteration 12800\n",
"Iteration 17200\n",
"Epoch 3\n",
"Shuffling dataset\n",
"Iteration 23200\n",
"Epoch 4\n",
"Shuffling dataset\n",
"Iteration 31200\n",
"Epoch 5\n",
"Shuffling dataset\n",
"Iteration 41600\n",
"Epoch 6\n",
"Shuffling dataset\n",
"Iteration 55600\n",
"Epoch 7\n",
"Shuffling dataset\n",
"Epoch 8\n",
"Shuffling dataset\n",
"Iteration 74400\n",
"Epoch 9\n",
"Shuffling dataset\n",
"Epoch 10\n",
"Shuffling dataset\n",
"Iteration 99600\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/opt/miniconda3/lib/python3.5/site-packages/matplotlib/axes/_axes.py:545: UserWarning: No labelled objects found. Use label='...' kwarg on individual plots.\n",
" warnings.warn(\"No labelled objects found. \"\n",
"INFO - decompose_images - Completed after 0:00:15\n",
"INFO - decompose_images - Running command 'decompose_run'\n",
"INFO - decompose_images - Started\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading data\n",
"Done\n",
"Preparing patch extraction\n",
"Fitting dictionary\n",
"Epoch 1\n",
"Iteration 0\n",
"Iteration 400\n",
"Iteration 800\n",
"Iteration 1200\n",
"Iteration 1600\n",
"Iteration 2000\n",
"Iteration 2400\n",
"Iteration 2800\n",
"Iteration 4000\n",
"Iteration 5200\n",
"Iteration 7200\n",
"Iteration 9600\n",
"Epoch 2\n",
"Shuffling dataset\n",
"Iteration 12800\n",
"Iteration 17200\n",
"Epoch 3\n",
"Shuffling dataset\n",
"Iteration 23200\n",
"Epoch 4\n",
"Shuffling dataset\n",
"Iteration 31200\n",
"Epoch 5\n",
"Shuffling dataset\n",
"Iteration 41600\n",
"Epoch 6\n",
"Shuffling dataset\n",
"Iteration 55600\n",
"Epoch 7\n",
"Shuffling dataset\n",
"Epoch 8\n",
"Shuffling dataset\n",
"Iteration 74400\n",
"Epoch 9\n",
"Shuffling dataset\n",
"Epoch 10\n",
"Shuffling dataset\n",
"Iteration 99600\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/opt/miniconda3/lib/python3.5/site-packages/matplotlib/axes/_axes.py:545: UserWarning: No labelled objects found. Use label='...' kwarg on individual plots.\n",
" warnings.warn(\"No labelled objects found. \"\n",
"INFO - decompose_images - Completed after 0:00:15\n"
]
}
],
"source": [
"for reduction in [2, 4, 8]:\n",
" %run \"/home/arthur/work/repos/modl/examples/decompose_images.py\" {\"with reduction=%s\" % reduction}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Retrieving experiment results\n",
"\n",
"#### Record structure"
]
},
{
"cell_type": "code",
"execution_count": 80,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"OrderedDict([('_id', ObjectId('5887543046695643db731b42')),\n",
" ('result', None),\n",
" ('stop_time', datetime.datetime(2017, 1, 24, 14, 18, 55, 536000)),\n",
" ('host',\n",
" OrderedDict([('os_info',\n",
" 'Linux-4.8.0-34-generic-x86_64-with-debian-stretch-sid'),\n",
" ('python_compiler',\n",
" 'GCC 4.4.7 20120313 (Red Hat 4.4.7-1)'),\n",
" ('cpu_count', 4),\n",
" ('cpu', 'Intel(R) Core(TM) i7-5600U CPU @ 2.60GHz'),\n",
" ('python_version', '3.5.2'),\n",
" ('os', 'Linux'),\n",
" ('hostname', 'sting')])),\n",
" ('artifacts',\n",
" [ObjectId('5887543f46695643db731b45'),\n",
" ObjectId('5887543f46695643db731b47')]),\n",
" ('captured_out',\n",
" 'Loading data\\nDone\\nPreparing patch extraction\\nFitting dictionary\\nEpoch 1\\nIteration 0\\nIteration 400\\nIteration 800\\nIteration 1200\\nIteration 1600\\nIteration 2000\\nIteration 2400\\nIteration 2800\\nIteration 4000\\nIteration 5200\\nIteration 7200\\nIteration 9600\\nEpoch 2\\nShuffling dataset\\nIteration 12800\\nIteration 17200\\nEpoch 3\\nShuffling dataset\\nIteration 23200\\nEpoch 4\\nShuffling dataset\\nIteration 31200\\nEpoch 5\\nShuffling dataset\\nIteration 41600\\nEpoch 6\\nShuffling dataset\\nIteration 55600\\nEpoch 7\\nShuffling dataset\\nEpoch 8\\nShuffling dataset\\nIteration 74400\\nEpoch 9\\nShuffling dataset\\nEpoch 10\\nShuffling dataset\\nIteration 99600\\n/opt/miniconda3/lib/python3.5/site-packages/matplotlib/axes/_axes.py:545: UserWarning: No labelled objects found. Use label=\\'...\\' kwarg on individual plots.\\n warnings.warn(\"No labelled objects found. \"\\n'),\n",
" ('comment', ''),\n",
" ('info',\n",
" OrderedDict([('time',\n",
" [0.6032489999999995,\n",
" 0.6511259999999992,\n",
" 0.6812989999999997,\n",
" 0.7262219999999995,\n",
" 0.7732840000000007,\n",
" 0.803182000000001,\n",
" 0.8309100000000007,\n",
" 0.8581420000000004,\n",
" 1.034260999999999,\n",
" 1.1649009999999986,\n",
" 1.3976119999999987,\n",
" 1.7095499999999983,\n",
" 1.9790199999999984,\n",
" 2.2480359999999973,\n",
" 2.7317269999999976,\n",
" 3.2829739999999976,\n",
" 4.036474999999996,\n",
" 5.004728999999996,\n",
" 6.368147999999996,\n",
" 8.140359999999996]),\n",
" ('final_score', 0.3129151531982422),\n",
" ('iter',\n",
" [0,\n",
" 400,\n",
" 800,\n",
" 1200,\n",
" 1600,\n",
" 2000,\n",
" 2400,\n",
" 2800,\n",
" 4000,\n",
" 5200,\n",
" 7200,\n",
" 9600,\n",
" 12800,\n",
" 17200,\n",
" 23200,\n",
" 31200,\n",
" 41600,\n",
" 55600,\n",
" 74400,\n",
" 99600]),\n",
" ('score',\n",
" [0.3430631140136719,\n",
" 0.33741717895507817,\n",
" 0.33258582275390625,\n",
" 0.32902226196289064,\n",
" 0.3262431475830078,\n",
" 0.32378815490722657,\n",
" 0.32216346923828126,\n",
" 0.32106963928222654,\n",
" 0.3192179431152344,\n",
" 0.31799544311523437,\n",
" 0.3168618884277344,\n",
" 0.31611777526855467,\n",
" 0.3157213818359375,\n",
" 0.31522994323730474,\n",
" 0.31470546630859375,\n",
" 0.31425535034179686,\n",
" 0.3139142895507812,\n",
" 0.3135675128173828,\n",
" 0.31322503295898435,\n",
" 0.3129183746337891])])),\n",
" ('config',\n",
" OrderedDict([('n_components', 50),\n",
" ('patch_size', [16, 16]),\n",
" ('alpha', 0.08),\n",
" ('verbose', 20),\n",
" ('test_size', 4000),\n",
" ('learning_rate', 0.92),\n",
" ('n_epochs', 10),\n",
" ('gray', False),\n",
" ('batch_size', 400),\n",
" ('seed', 704892404),\n",
" ('scale', 1),\n",
" ('setting', 'dictionary learning'),\n",
" ('source', 'lisboa'),\n",
" ('method', 'masked'),\n",
" ('n_threads', 2),\n",
" ('max_patches', 10000),\n",
" ('reduction', 2)])),\n",
" ('status', 'COMPLETED'),\n",
" ('experiment',\n",
" OrderedDict([('name', 'decompose_images'),\n",
" ('dependencies',\n",
" [['IPython', '5.1.0'],\n",
" ['matplotlib', '2.0.0'],\n",
" ['modl', '0.5'],\n",
" ['numpy', '1.11.3'],\n",
" ['sacred', '0.6.10']]),\n",
" ('doc', 'Module created for script run in IPython'),\n",
" ('sources',\n",
" [['/home/arthur/work/repos/modl/examples/decompose_images.py',\n",
" '7e8fa8a80c2f4b5b4b354d2425308ea7']])])),\n",
" ('resources', []),\n",
" ('heartbeat', datetime.datetime(2017, 1, 24, 14, 18, 55, 536000)),\n",
" ('start_time',\n",
" datetime.datetime(2017, 1, 24, 14, 18, 40, 240000))])"
]
},
"execution_count": 80,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"result = collection.find_one({})\n",
"result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Comparing experiments, basic"
]
},
{
"cell_type": "code",
"execution_count": 81,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Reduction: 2, score: [0.3430631140136719, 0.33741717895507817, 0.33258582275390625, 0.32902226196289064, 0.3262431475830078, 0.32378815490722657, 0.32216346923828126, 0.32106963928222654, 0.3192179431152344, 0.31799544311523437, 0.3168618884277344, 0.31611777526855467, 0.3157213818359375, 0.31522994323730474, 0.31470546630859375, 0.31425535034179686, 0.3139142895507812, 0.3135675128173828, 0.31322503295898435, 0.3129183746337891]\n",
"Reduction: 4, score: [0.3413323718261719, 0.3391186999511719, 0.33669017822265623, 0.33468490234375, 0.3328418908691406, 0.330773212890625, 0.3292049987792969, 0.3274899914550781, 0.32402357604980464, 0.3219119171142578, 0.3198845349121094, 0.3185772479248047, 0.3177424334716797, 0.31712832031250004, 0.31665446411132814, 0.31613582031250004, 0.31570132507324217, 0.31534347167968746, 0.3149916351318359, 0.31465369140625]\n",
"Reduction: 8, score: [0.34424404541015624, 0.3434152209472657, 0.3423750866699219, 0.34114804443359376, 0.3393632836914062, 0.33806236328125, 0.33661517822265624, 0.3356642211914062, 0.3322289916992187, 0.32876122985839845, 0.3256145855712891, 0.32314545043945314, 0.3210167053222656, 0.3197013452148437, 0.3185593310546875, 0.3181461193847656, 0.3177547509765625, 0.31732104919433596, 0.31701679565429686, 0.3167107141113281]\n",
"Reduction: 2, score: [0.34750017578125, 0.34229627685546876, 0.3380082080078125, 0.334469267578125, 0.3323436584472656, 0.33050134765625, 0.3292404193115235, 0.3282515582275391, 0.32624876037597655, 0.3251650994873047, 0.3240159545898438, 0.3232660766601563, 0.3227937487792969, 0.3222846807861328, 0.3220490252685547, 0.3220765161132813, 0.32200451232910154, 0.32187505493164065, 0.32172772033691405, 0.32157206176757813]\n",
"Reduction: 4, score: [0.3429542541503906, 0.3405890466308593, 0.33831430786132816, 0.3359746923828125, 0.3340643200683594, 0.3325248974609375, 0.3306192541503906, 0.3291674816894531, 0.325946142578125, 0.3242040802001953, 0.32199115173339843, 0.3207570886230469, 0.3200161053466797, 0.3194488208007813, 0.3190960656738281, 0.31912391784667965, 0.3189858959960937, 0.3188132659912109, 0.31862385131835935, 0.3184357751464844]\n",
"Reduction: 8, score: [0.34930876708984376, 0.3481751257324219, 0.3467903137207031, 0.34515155029296873, 0.34344275634765625, 0.34202519165039064, 0.3404373681640625, 0.33921915283203125, 0.3360492895507813, 0.3330937451171875, 0.3297158740234375, 0.32709095947265626, 0.32475197570800785, 0.3233050518798828, 0.3224851452636719, 0.32229433166503907, 0.32215194030761723, 0.3219684832763672, 0.32168022033691407, 0.3213801495361328]\n",
"Reduction: 2, score: [0.343791875, 0.3384177392578125, 0.33438750732421874, 0.3308684497070312, 0.32772093200683594, 0.32543758361816405, 0.323885443725586, 0.3228956219482422, 0.32076180603027343, 0.3194201232910156, 0.31828013916015624, 0.3174560632324219, 0.31685074768066407, 0.3162279431152344, 0.315943125, 0.31601864318847656, 0.3159025274658203, 0.3157103741455078, 0.3155034027099609, 0.31530184814453127]\n",
"Reduction: 4, score: [0.3453605541992188, 0.3431004138183594, 0.34056810302734375, 0.33836002685546873, 0.3359398840332032, 0.33389548950195314, 0.3320941247558594, 0.3302763720703125, 0.3267206134033203, 0.32357675537109376, 0.32079480957031253, 0.31923461303710937, 0.3184367712402344, 0.3175317541503906, 0.3169107586669922, 0.31706892822265625, 0.31690133117675784, 0.3166727264404297, 0.3164220635986328, 0.31616223571777347]\n",
"Reduction: 8, score: [0.34562197265625, 0.3445701318359375, 0.3436396057128906, 0.34208275024414064, 0.3408962158203125, 0.3395554919433594, 0.33766634399414064, 0.3357778845214844, 0.3322569787597656, 0.3294194067382813, 0.3260795440673828, 0.3229664678955078, 0.3210501336669922, 0.3199370642089844, 0.31920353759765624, 0.3190012292480469, 0.31877233825683593, 0.3184721014404297, 0.3181827008056641, 0.3178681182861328]\n"
]
}
],
"source": [
"results = collection.find({})\n",
"for result in results:\n",
" print('Reduction: %s, score: %s' % (result['config']['reduction'], result['info']['score']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Plotting with aggregate"
]
},
{
"cell_type": "code",
"execution_count": 82,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"pipeline = [{\"$match\": {\"config.method\": \"gram\"}}, \n",
" {\"$project\": {\"reduction\": \"$config.reduction\", \"score\": \"$info.score\", \"time\": \"$info.time\",\n",
" \"iter\": \"$info.iter\", \"stop_time\": 1}},\n",
" {\"$sort\": {\"stop_time\": pymongo.DESCENDING}},\n",
" {\"$group\": {\"_id\": \"$reduction\",\n",
" \"score\": {\"$last\": \"$score\"},\n",
" \"time\": {\"$last\": \"$time\"},\n",
" \"iter\": {\"$last\": \"$iter\"}\n",
" }},\n",
" {\"$sort\": {\"_id\": pymongo.ASCENDING}}]\n",
"results = collection.aggregate(pipeline)\n",
"results = list(results)"
]
},
{
"cell_type": "code",
"execution_count": 83,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "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\nlsl/uz6OTlt4mBUAAAAASUVORK5CYII=\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f2c9a40cef0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig = plt.figure()\n",
"ax = fig.add_subplot(111)\n",
"for result in results:\n",
" ax.plot(result['time'], result['score'], label=\"%.0f\" % result['_id'], marker='o')\n",
"ax.legend(title='Reduction')\n",
"ax.set_xlabel('Time (s)')\n",
"ax.set_ylabel('Function value')\n",
"ax.set_xscale('log')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"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.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment