├── MANIFEST.in ├── .gitignore ├── Oscar ├── __init__.py ├── __init__.pyc └── Oscar.py ├── README.md ├── setup.py └── example.py /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.md 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /Oscar/__init__.py: -------------------------------------------------------------------------------- 1 | from Oscar import Oscar -------------------------------------------------------------------------------- /Oscar/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calldesk/Oscar-Python/HEAD/Oscar/__init__.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Oscar's Python client 2 | ================== 3 | 4 | This is the Python client for Oscar. 5 | 6 | Install 7 | ------- 8 | 9 | pip install git+git://github.com/calldesk/Oscar-Python.git 10 | 11 | Usage 12 | ----- 13 | 14 | Read the [docs](http://oscar.calldesk.fr/documentation.html) and have a look at [exemple.py](https://github.com/calldesk/Oscar-Python/blob/master/example.py). 15 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from setuptools import setup, find_packages 4 | 5 | import Oscar 6 | 7 | setup( 8 | name='Oscar', 9 | packages=find_packages(), 10 | author="SensOut", 11 | author_email="@SensOut", 12 | description="Oscar's Python client", 13 | long_description=open('README.md').read(), 14 | # take into account MANIFEST.in 15 | include_package_data=True, 16 | url='http://oscar.sensout.com' 17 | ) -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | # set up Oscar 2 | from Oscar import Oscar 3 | ACCESS_TOKEN ='copy the access token from your Account panel here' 4 | scientist = Oscar(ACCESS_TOKEN) 5 | 6 | # define your experiment hyperparameters' space here 7 | experiment = { 8 | 'name' : 'test', 9 | 'parameters' : { 10 | 'x' : { 'min' : -2, 'max' : 2 }, 11 | 'c' : [ 3, 4, 5 ] 12 | } 13 | } 14 | 15 | # get a job suggestion 16 | job = scientist.suggest(experiment) 17 | print job 18 | 19 | # do your complex job here 20 | from random import randint 21 | import math 22 | duration = randint(1, 100) 23 | loss = math.pow(job['x'] * job['c'], 2) 24 | result = { 25 | 'loss' : loss, 26 | 'duration' : duration 27 | } 28 | 29 | # update Oscar 30 | print result 31 | scientist.update(job, result) -------------------------------------------------------------------------------- /Oscar/Oscar.py: -------------------------------------------------------------------------------- 1 | import json 2 | import urllib 3 | import urllib2 4 | 5 | __all__ = ['Oscar', 'ClientException'] 6 | 7 | class ClientException(Exception): 8 | pass 9 | 10 | class Oscar: 11 | API_VERSION = '1' 12 | #DOMAIN_URL = 'http://localhost:8080' 13 | DOMAIN_URL = 'https://' + API_VERSION + '-dot-sensout-oscar.appspot.com' 14 | 15 | def __init__(self, access_token): 16 | self.access_token = access_token 17 | self.trial_ids = {} 18 | self.trial_keys = {} 19 | 20 | def call(self, url, params): 21 | # prepare request 22 | headers = {'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer ' + self.access_token} 23 | url = url + '?' + urllib.urlencode(params) 24 | req = urllib2.Request(self.DOMAIN_URL + url, None, headers) 25 | try: 26 | resp = urllib2.urlopen(req) 27 | content = resp.read() 28 | result = json.loads(content) 29 | if result: 30 | if 'redirect' in result: 31 | raise ClientException("Your are not authenticated. You should try updating your access token.") 32 | else: 33 | return result 34 | else: 35 | raise ClientException("Did not manage to parse API response: " + content) 36 | except Exception as e: 37 | print "Error when calling API:" 38 | raise e 39 | 40 | def get_job_hash(self, job): 41 | return str(hash(json.dumps(job))) 42 | 43 | def get_job_id(self, job): 44 | return self.trial_ids[self.get_job_hash(job)] 45 | 46 | def suggest(self, experiment): 47 | result = self.call('/suggest', { 48 | 'experiment' : json.dumps(experiment) 49 | }) 50 | # result is non nil or error has been raised 51 | if 'job' in result and 'trial_key' in result and 'trial_id' in result: 52 | hash = self.get_job_hash(result['job']) 53 | self.trial_ids[hash] = result['trial_id'] 54 | self.trial_keys[hash] = result['trial_key'] 55 | return result['job'] 56 | else: 57 | raise ClientException("No job returned. Check your parameters and quotas " + json.dumps(result)) 58 | 59 | def update(self, job, result): 60 | return self.call('/update', { 61 | 'trial_key' : self.trial_keys[self.get_job_hash(job)], 62 | 'result' : json.dumps(result) 63 | }) 64 | --------------------------------------------------------------------------------