deepdetect_ruby 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,241 @@
1
+ # Finetuning
2
+ ```
3
+ DeepdetectRuby::Service.create({name: "selfie_finetuning", model_name: "selfie_finetuning", finetuning: true, weights: "model_iter_16368.caffemodel"})
4
+
5
+ DeepdetectRuby::Service.create({name: "selfie_finetuning_t1", finetuning: true, weights: "model_iter_16368.caffemodel"})
6
+
7
+ DeepdetectRuby::Service.create({name: "selfie_finetuning_t2", finetuning: true, weights: "model_iter_16368.caffemodel"})
8
+
9
+ DeepdetectRuby::Service.delete("selfie_finetuning")
10
+
11
+ DeepdetectRuby::Train.get_status(service: "selfie_finetuning")
12
+
13
+ DeepdetectRuby::Train.get_status(service: "selfie_finetuning_t1")
14
+
15
+ DeepdetectRuby::Service.finetuning({name: "selfie_finetuning", finetuning: true, weights: "model_iter_16368.caffemodel", repository: "/home/ubuntu/training/finetuning/selfie", gpu: true, iterations: 16368, test_interval: 500})
16
+
17
+ DeepdetectRuby::Service.finetuning({name: "person_yes_no_f1", finetuning: true, weights: "model_iter_5213.caffemodel", repository: "/home/ubuntu/training/finetuning/person_yes_no", gpu: true, iterations: 10000, test_interval: 500})
18
+
19
+ DeepdetectRuby::Service.finetuning({name: "selfie_f1", finetuning: true, weights: "model_iter_16368.caffemodel", repository: "/home/ubuntu/training/finetuning/selfie", gpu: true, iterations: 18000, test_interval: 500})
20
+
21
+ DeepdetectRuby::Service.finetuning({name: "selfie_f2", finetuning: true, weights: "model_iter_18000.caffemodel", repository: "/home/ubuntu/training/finetuning/selfie_f2", gpu: true, iterations: 18000, test_interval: 500})
22
+
23
+ DeepdetectRuby::Service.finetuning({name: "more_than_one_f1", finetuning: true, weights: "model_iter_15000.caffemodel", repository: "/home/ubuntu/training/finetuning/more_than_one", gpu: true, iterations: 18000, test_interval: 500})
24
+
25
+ DeepdetectRuby::Service.finetuning({name: "selfie_f2_1", finetuning: true, weights: "model_iter_18000.caffemodel", repository: "/home/ubuntu/training/finetuning/selfie_f2", gpu: true, iterations: 18000, test_interval: 500})
26
+
27
+ DeepdetectRuby::Service.finetuning({name: "selfie_f3", finetuning: true, weights: "model_iter_16368.caffemodel", repository: "/home/ubuntu/training/finetuning/selfie_f2", gpu: true, iterations: 10230, test_interval: 500, measure_index: 2})
28
+
29
+ DeepdetectRuby::Service.finetuning({name: "selfie_f4", finetuning: true, weights: "model_iter_16368.caffemodel", repository: "/home/ubuntu/training/finetuning/selfie_f4", gpu: true, iterations: 20002, test_interval: 500, measure_index: 1, batch_size: 32, test_batch_size: 32})
30
+
31
+ ```
32
+ ## Training new updated models with finetuning
33
+ ```
34
+ DeepdetectRuby::Train.launch({service: "selfie_finetuning", repository: "/home/ubuntu/training/finetuning/selfie", gpu: true, iterations: 16368})
35
+
36
+ DeepdetectRuby::Train.launch({service: "selfie_finetuning_t1", repository: "/home/ubuntu/training/finetuning/selfie", gpu: true, iterations: 16368, test_interval: 500})
37
+
38
+ DeepdetectRuby::Train.launch({service: "selfie_finetuning_t2", repository: "/home/ubuntu/training/finetuning/selfie", gpu: true, iterations: 16368, test_interval: 500, finetuning: true})
39
+ ```
40
+ --------------------------------------------------------------
41
+ Create a service
42
+ curl -X PUT "http://localhost:8080/services/selfie" -d "{\"mllib\":\"caffe\",\"description\":\"selfie classification\",\"type\":\"supervised\",\"parameters\":{\"input\":{\"connector\":\"image\",\"height\":224,\"width\":224},\"mllib\":{\"nclasses\":304}},\"model\":{\"repository\":\"/home/ubuntu/projects/deepdetect_u1/models/selfie_f40\"}}"
43
+ --------------------------------------------------------------
44
+ Finetuning model selfie_f3
45
+ curl -X PUT "http://localhost:8080/services/selfie" -d "{\"mllib\":\"caffe\",\"description\":\"selfie classification\",\"type\":\"supervised\",\"parameters\":{\"input\":{\"connector\":\"image\",\"height\":224,\"width\":224},\"mllib\":{\"nclasses\":2, \"mirror\":true, \"weights\":\"model_iter_16368.caffemodel\",\"finetuning\":true, \"gpu\":true}},\"model\":{\"repository\":\"/home/ubuntu/projects/deepdetect_u1/models/selfie_f40\"}}"
46
+
47
+ curl -X POST "http://localhost:8080/train" -d "{\"service\":\"selfie\",\"async\":true,\"parameters\":{\"mllib\":{\"gpu\":true,\"net\":{\"batch_size\":32},\"solver\":{\"test_interval\":500,\"iterations\":18000,\"base_lr\":0.0001,\"stepsize\":1000,\"gamma\":0.9}},\"input\":{\"connector\":\"image\",\"test_split\":0.1,\"shuffle\":true,\"width\":224,\"height\":224},\"output\":{\"measure\":[\"acc-5\",\"mcll\",\"f1\"]}},\"data\":[\"/home/ubuntu/training/finetuning/selfie_f4\"]}"
48
+ --------------------------------------------------------------
49
+
50
+ curl -X POST "http://localhost:8080/train" -d "{\"service\":\"selfie_finetuning\",\"async\":true,\"parameters\":{\"mllib\":{\"gpu\":true,\"net\":{\"batch_size\":32},\"solver\":{\"test_interval\":500,\"iterations\":10000,\"base_lr\":0.001,\"stepsize\":1000,\"gamma\":0.9}},\"input\":{\"connector\":\"image\",\"test_split\":0.1,\"shuffle\":true,\"width\":224,\"height\":224},\"output\":{\"measure\":[\"acc\",\"mcll\",\"f1\"]}},\"data\":[\"/home/ubuntu/training/finetuning/selfie\"]}"
51
+
52
+ --------------------------
53
+ DeepdetectRuby::Predict.predict({service: "selfie_finetuning", image_url: "http://cdn.feels.com/instagram/asos/1246490803437553418_1557663056.jpg"})
54
+
55
+ DeepdetectRuby::Predict.predict({service: "person_yes_no_f1", image_url: "http://cdn.feels.com/instagram/asos/1246490803437553418_1557663056.jpg"})
56
+ ## Before finetuning
57
+ :predictions => {
58
+ :uri => "http://cdn.feels.com/instagram/asos/1246490803437553418_1557663056.jpg",
59
+ :classes => [
60
+ [0] {
61
+ :prob => 0.5820828080177307,
62
+ :cat => "selfie"
63
+ },
64
+ [1] {
65
+ :last => true,
66
+ :prob => 0.4179171919822693,
67
+ :cat => "no_selfie"
68
+ }
69
+ ]
70
+ }
71
+
72
+ ## After finetuning
73
+ :predictions => {
74
+ :uri => "http://cdn.feels.com/instagram/asos/1246490803437553418_1557663056.jpg",
75
+ :classes => [
76
+ [0] {
77
+ :prob => 0.9999997615814209,
78
+ :cat => "selfie"
79
+ },
80
+ [1] {
81
+ :last => true,
82
+ :prob => 2.4337700210708135e-07,
83
+ :cat => "no_selfie"
84
+ }
85
+ ]
86
+ }
87
+
88
+ -----------------------------
89
+ http://feels.imgix.net/instagram/asos/1252542985950992360_2206765260.jpg?w=530&h=530&dpr=2&fit=crop&crop=faces,top
90
+ Origin:
91
+ https://www.instagram.com/p/BFh7TWfhBfo/
92
+ {"normal_resolution":0.990632,"bad_resolution":0.00936781,"normal_lighting":0.987771,"poor_lighting":0.0122286,"someone":0.901468,"no_one":0.0985324,"less_than_one":0.998956,"more_than_one":0.0010435,"men":0.562763,"women":0.437237,"age_above_30":0.40452,"selfie":0.880388,"no_selfie":0.119612,"no_mirrorshot":0.962171,"mirrorshot":0.0378293}
93
+
94
+ After finetuning:
95
+ ---> DeepdetectRuby::Predict.predict({service: "selfie_finetuning_t1", image_url: "http://feels.imgix.net/instagram/asos/1252542985950992360_2206765260.jpg?w=530&h=530&dpr=2&fit=crop&crop=faces,top"})
96
+
97
+ :predictions => {
98
+ :uri => "http://feels.imgix.net/instagram/asos/1252542985950992360_2206765260.jpg?w=530&h=530&dpr=2&fit=crop&crop=faces,top",
99
+ :classes => [
100
+ [0] {
101
+ :prob => 0.9978917241096497,
102
+ :cat => "no_selfie"
103
+ },
104
+ [1] {
105
+ :last => true,
106
+ :prob => 0.002108336426317692,
107
+ :cat => "selfie"
108
+ }
109
+ ]
110
+ }
111
+
112
+ -----------------------------
113
+ http://feels.imgix.net/instagram/asos/1252353525430668710_1814295050.jpg?w=530&h=530&dpr=2&fit=crop&crop=faces,top
114
+ Origin: https://www.instagram.com/p/BFhQOVogM2m/
115
+ {"normal_resolution":0.825466,"bad_resolution":0.174534,"normal_lighting":0.884736,"poor_lighting":0.115264,"someone":0.999343,"no_one":0.000656711,"more_than_one":0.845909,"less_than_one":0.154091,"men":1,"women":1.60751e-10,"age_under_16":0.917247,"selfie":0.976695,"no_selfie":0.0233054,"no_mirrorshot":0.996792,"mirrorshot":0.00320824}
116
+
117
+ After finetuning:
118
+ ---> DeepdetectRuby::Predict.predict({service: "selfie_finetuning_t1", image_url: "http://feels.imgix.net/instagram/asos/1252353525430668710_1814295050.jpg?w=530&h=530&dpr=2&fit=crop&crop=faces,top"})
119
+ ------------------------------
120
+ http://feels.imgix.net/instagram/asos/1251924354355760960_14740578.jpg?w=530&h=530&dpr=2&fit=crop&crop=faces,top
121
+ {"normal_resolution":0.996735,"bad_resolution":0.00326459,"normal_lighting":0.971896,"poor_lighting":0.0281036,"someone":0.878907,"no_one":0.121093,"less_than_one":0.935041,"more_than_one":0.0649591,"women":0.999993,"men":0.00000736875,"age_above_30":0.567047,"selfie":0.863574,"no_selfie":0.136426,"no_mirrorshot":0.996853,"mirrorshot":0.00314677}
122
+ DeepdetectRuby::Predict.predict({service: "selfie_finetuning_t1", image_url: "http://feels.imgix.net/instagram/asos/1251924354355760960_14740578.jpg?w=530&h=530&dpr=2&fit=crop&crop=faces,top"})
123
+ :predictions => {
124
+ :uri => "http://feels.imgix.net/instagram/asos/1251924354355760960_14740578.jpg?w=530&h=530&dpr=2&fit=crop&crop=faces,top",
125
+ :classes => [
126
+ [0] {
127
+ :prob => 1.0,
128
+ :cat => "selfie"
129
+ },
130
+ [1] {
131
+ :last => true,
132
+ :prob => 5.714219852848146e-08,
133
+ :cat => "no_selfie"
134
+ }
135
+ ]
136
+ }
137
+ -------------------------------------
138
+ http://feels.imgix.net/instagram/asos/1251985366878743528_10194825.jpg?w=530&h=530&dpr=2&fit=crop&crop=faces,top
139
+ https://www.instagram.com/p/BFf8g7Qy2vo/
140
+ {"someone":1,"no_one":0,"selfie":1,"women":1,"men":0,"no_selfie":0,"normal_resolution":0.999719,"bad_resolution":0.000280655,"normal_lighting":0.998396,"poor_lighting":0.00160362,"less_than_one":0.912216,"more_than_one":0.0877836,"age_above_30":0.469602}
141
+
142
+ DeepdetectRuby::Predict.predict({service: "selfie_finetuning_t1", image_url: "http://feels.imgix.net/instagram/asos/1252033944498407117_1223425960.jpg?w=530&h=530&dpr=2&fit=crop&crop=faces,top"})
143
+
144
+ DeepdetectRuby::Predict.predict({service: "selfie_finetuning_t2", image_url: "http://feels.imgix.net/instagram/asos/1252404500268043866_27876266.jpg"})
145
+
146
+ DeepdetectRuby::Predict.predict({service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255170406470979359_3253319674.jpg"})
147
+
148
+ DeepdetectRuby::Predict.predict({service: "selfie_f1", image_url: "//feels.imgix.net/instagram/asos/1255355896542752718_27057010.jpg"})
149
+
150
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255266658690557670_11397328.jpg")
151
+
152
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255271338485499066_775122576.jpg")
153
+
154
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255424592408535294_185254919.jpg")
155
+
156
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255390340978924420_15115085.jpg")
157
+
158
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255662739004227204_330560670.jpg") --> not ok, must be selfie
159
+
160
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255602514657391462_15783947.jpg")
161
+
162
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255622208398307634_317677827.jpg") --> not ok, must be selfie
163
+
164
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255534513632110008_553559664.jpg")
165
+
166
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255455561021981994_197430064.jpg") --> not ok, must be selfie
167
+
168
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255399707491145944_1457907277.jpg")
169
+
170
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255337649249306267_558272928.jpg")
171
+
172
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://feels.imgix.net/instagram/asos/1255237247935534338_238585596.jpg")
173
+
174
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://cdn.feels.com/instagram/asos/1256146576133469486_222484236.jpg")
175
+
176
+ DeepdetectRuby::Predict.predict(service: "selfie_f1", image_url: "http://cdn.feels.com/instagram/asos/1256146220572730237_30723063.jpg")
177
+
178
+ DeepdetectRuby::Predict.predict(service: "more_than_one_f1", image_url: "http://cdn.feels.com/instagram/asos/1256909233581381035_264705436.jpg")
179
+
180
+ DeepdetectRuby::Predict.predict(service: "more_than_one_f1", image_url: "http://cdn.feels.com/instagram/asos/1256902797330248703_3013321051.jpg")
181
+
182
+ DeepdetectRuby::Predict.predict(service: "more_than_one_f1", image_url: "http://feels.imgix.net/instagram/asos/1256951961487542817_1462068201.jpg")
183
+
184
+ DeepdetectRuby::Predict.predict(service: "selfie_f2_1", image_url: "http://feels.imgix.net/instagram/newlookfashion/1231213665197843799_1452988672.jpg") --> error
185
+
186
+ DeepdetectRuby::Predict.predict(service: "selfie_f3", image_url: "http://feels.imgix.net/instagram/newlookfashion/1231213665197843799_1452988672.jpg")
187
+
188
+ curl -X POST "http://localhost:8080/predict" -d "{\"service\":\"selfie_f3\",\"parameters\":{\"output\":{\"best\":2}},\"data\":[\"http://feels.imgix.net/instagram/newlookfashion/1231213665197843799_1452988672.jpg\"]}"
189
+ --------------------------
190
+ http://cdn.feels.com/instagram/newlookfashion/1221769581631587626_433120464.jpg
191
+ old predict: --> bad, wrong result
192
+ DeepdetectRuby::Predict.predict(service: "selfie", image_url: "http://cdn.feels.com/instagram/newlookfashion/1221769581631587626_433120464.jpg")
193
+ :predictions => {
194
+ :uri => "http://cdn.feels.com/instagram/newlookfashion/1221769581631587626_433120464.jpg",
195
+ :classes => [
196
+ [0] {
197
+ :prob => 0.95999675989151,
198
+ :cat => "selfie"
199
+ },
200
+ [1] {
201
+ :last => true,
202
+ :prob => 0.040003255009651184,
203
+ :cat => "no_selfie"
204
+ }
205
+ ]
206
+ }
207
+
208
+ new predict: --> better, more accuracy
209
+ DeepdetectRuby::Predict.predict(service: "selfie_f3", image_url: "http://cdn.feels.com/instagram/newlookfashion/1221769581631587626_433120464.jpg")
210
+ :predictions => {
211
+ :uri => "https://feels.imgix.net/instagram/newlookfashion/1221769581631587626_433120464.jpg",
212
+ :classes => [
213
+ [0] {
214
+ :prob => 0.8537927865982056,
215
+ :cat => "no_selfie"
216
+ },
217
+ [1] {
218
+ :last => true,
219
+ :prob => 0.14620719850063324,
220
+ :cat => "selfie"
221
+ }
222
+ ]
223
+ }
224
+
225
+ -------------------
226
+ OpenCV Error: Assertion failed (buf.data && buf.isContinuous()) in imdecode_, file /build/buildd/opencv-2.4.8+dfsg1/modules/highgui/src/loadsave.cpp, line 307
227
+
228
+ ERROR - 02:32:08 - service selfie_f3 mllib bad param: /build/buildd/opencv-2.4.8+dfsg1/modules/highgui/src/loadsave.cpp:307: error: (-215) buf.data && buf.isContinuous() in function imdecode_
229
+
230
+ ------------------------
231
+ DeepdetectRuby::Predict.predict(service: "mirrorshot_f1", image_url: "http://cdn.feels.com/instagram/converse/1286789533837253555_412988956.jpg")
232
+ DeepdetectRuby::Predict.predict(service: "mirrorshot_f1", image_url: "http://cdn.feels.com/instagram/converse/1286744821742913513_1637327762.jpg")
233
+
234
+ ------------------------
235
+ DeepdetectRuby::Predict.predict(service: "more_than_one_c", image_url: "http://feels.imgix.net/instagram/asos/1256951961487542817_1462068201.jpg")
236
+
237
+ DeepdetectRuby::Predict.predict(service: "more_than_one_c", image_url: "http://cdn.feels.com/instagram/missguided/1293683001124816735_215780245.jpg")
238
+
239
+
240
+ -------------------
241
+ ## Rsync
@@ -0,0 +1,28 @@
1
+ from dd_client import DD
2
+
3
+ model_repo = '/home/me/models/sent_en_char'
4
+ nclasses = 2
5
+
6
+ # setting up DD client
7
+ host = '127.0.0.1'
8
+ sname = 'sent_en'
9
+ description = 'English sentiment classification'
10
+ mllib = 'caffe'
11
+ dd = DD(host)
12
+ dd.set_return_format(dd.RETURN_PYTHON)
13
+
14
+ # creating ML service
15
+ model = {'repository':model_repo}
16
+ parameters_input = {'connector':'txt','characters':True,'sequence':140,'alphabet':"abcdefghijklmnopqrstuvwxyz0123456789,;.!?'"}
17
+ parameters_mllib = {'nclasses':nclasses}
18
+ parameters_output = {}
19
+ dd.put_service(sname,model,description,mllib,
20
+ parameters_input,parameters_mllib,parameters_output)
21
+
22
+ # classifying a single piece of text:
23
+ parameters_input = {}
24
+ parameters_mllib = {}
25
+ parameters_output = {}
26
+ data = ['Chilling in the West Indies']
27
+ classif = dd.post_predict(sname,data,parameters_input,parameters_mllib,parameters_output)
28
+ print classif
data/docs/dd_client.py ADDED
@@ -0,0 +1,379 @@
1
+ """
2
+ DeepDetect Python client
3
+
4
+ Licence:
5
+ Copyright (c) 2015 Emmanuel Benazera
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12
+
13
+ """
14
+
15
+ try:
16
+ import urllib.request as urllib2
17
+ except ImportError:
18
+ import urllib2
19
+
20
+ try:
21
+ import http.client as httplib
22
+ except ImportError:
23
+ import httplib
24
+
25
+
26
+ import os.path
27
+ import json
28
+ import uuid
29
+ import datetime
30
+
31
+
32
+ VERBOSE=False
33
+ DD_TIMEOUT = 2000 # seconds, for long blocking training alls, as needed
34
+
35
+ def LOG(msg):
36
+ """Output a log message."""
37
+ # XXX: may want to use python log manager classes instead of this stupid print
38
+ if VERBOSE:
39
+ msg = str(datetime.datetime.now()) + ' ' + msg
40
+ print (msg)
41
+
42
+ ### Exception classes :
43
+
44
+ class DDCommunicationError(Exception):
45
+ def __init__(self, url, http_method, headers, body, response=None):
46
+ self.msg = """DeepDetect Communication Error"""
47
+ self.http_method = http_method
48
+ self.req_headers = headers
49
+ self.req_body = body
50
+ self.url = url
51
+ self.res_headers = None
52
+ if response is not None:
53
+ self.res_headers = response.get_info()
54
+
55
+ def __str__(self):
56
+ msg = "%s %s\n"%(str(self.http_method),str(self.url))
57
+ for h,v in self.req_headers.iteritems():
58
+ msg += "%s:%s\n"%(h,v)
59
+ msg += "\n"
60
+ if self.req_body is not None:
61
+ msg += str(self.req_body)[:100]
62
+ msg += "\n"
63
+ msg += "--\n"
64
+ msg += str(self.res_headers)
65
+ msg += "\n"
66
+ return msg
67
+
68
+ class DDDataError(Exception):
69
+ def __init__(self, url, http_method, headers, body, data=None):
70
+ self.msg = "DeepDetect Data Error"
71
+ self.http_method = http_method
72
+ self.req_headers = headers
73
+ self.req_body = body
74
+ self.url = url
75
+ self.data = data
76
+
77
+ def __str__(self):
78
+ msg = "%s %s\n"%(str(self.http_method),str(self.url))
79
+ if self.data is not None:
80
+ msg += str(self.data)[:100]
81
+ msg += "\n"
82
+ for h,v in self.req_headers.iteritems():
83
+ msg += "%s:%s\n"%(h,v)
84
+ msg += "\n"
85
+ if self.req_body is not None:
86
+ msg += str(self.req_body)
87
+ msg += "\n"
88
+ msg += "--\n"
89
+ msg += str(self.data)
90
+ msg += "\n"
91
+ return msg
92
+
93
+ API_METHODS_URL = {
94
+ "0.1" : {
95
+ "info":"/info",
96
+ "services":"/services",
97
+ "train":"/train",
98
+ "predict":"/predict"
99
+ }
100
+ }
101
+
102
+ class DD(object):
103
+ """HTTP requests to the DeepDetect server
104
+
105
+ """
106
+
107
+ # return types
108
+ RETURN_PYTHON=0
109
+ RETURN_JSON=1
110
+ RETURN_NONE=2
111
+
112
+ __HTTP=0
113
+ __HTTPS=1
114
+
115
+ def __init__(self,host="localhost",port=8080,proto=0,apiversion="0.1"):
116
+ """ DD class constructor
117
+ Parameters:
118
+ host -- the DeepDetect server host
119
+ port -- the DeepDetect server port
120
+ proto -- user http (0,default) or https connection
121
+ """
122
+ self.apiversion = apiversion
123
+ self.__urls = API_METHODS_URL[apiversion]
124
+ self.__host = host
125
+ self.__port = port
126
+ self.__proto = proto
127
+ self.__returntype=self.RETURN_PYTHON
128
+ if proto == self.__HTTP:
129
+ self.__ddurl='http://%s:%d'%(host,port)
130
+ else:
131
+ self.__ddurl='https://%s:%d'%(host,port)
132
+
133
+
134
+ def set_return_format(self,f):
135
+ assert f == self.RETURN_PYTHON or f == self.RETURN_JSON or f == self.RETURN_NONE
136
+ self.__returntype = f
137
+
138
+ def __return_format(self,js):
139
+ if self.__returntype == self.RETURN_PYTHON:
140
+ return json.loads(js.decode('utf-8'))
141
+ elif self.__returntype == self.RETURN_JSON:
142
+ return js
143
+ else:
144
+ return None
145
+
146
+ def get(self,method,args=None):
147
+ """ GET to DeepDetect server """
148
+ u = self.__ddurl
149
+ u += method
150
+ headers = {}
151
+ if args is not None:
152
+ sep = "?"
153
+ for arg,argv in args.iteritems():
154
+ u += sep
155
+ sep = "&"
156
+ u += urllib2.quote(arg)
157
+ u += '='
158
+ if argv is not None:
159
+ u += urllib2.quote(argv)
160
+
161
+ LOG("GET %s"%u)
162
+ response = None
163
+ try:
164
+ req = urllib2.Request(u)
165
+ response = urllib2.urlopen(req, timeout=DD_TIMEOUT)
166
+ jsonresponse=response.read()
167
+ except:
168
+ raise DDCommunicationError(u,"GET",headers,None,response)
169
+ LOG(jsonresponse)
170
+ try:
171
+ return self.__return_format(jsonresponse)
172
+ except:
173
+ raise DDDataError(u,"GET",headers,None,jsonresponse)
174
+
175
+ def put(self, method, body):
176
+ """PUT request to DeepDetect server"""
177
+
178
+ LOG("PUT %s\n%s"%(method,body))
179
+ r = None
180
+ u = ""
181
+ headers = {}
182
+ try:
183
+ u = self.__ddurl + method
184
+ if self.__proto == self.__HTTP:
185
+ # u = "http://%s:%s%s"%(self.__host,self.__port,method)
186
+ c=httplib.HTTPConnection(self.__host,self.__port, timeout=DD_TIMEOUT)
187
+ else:
188
+ # u = "https://%s:%s%s"%(self.__host,self.__port,method)
189
+ c=httplib.HTTPSConnection(self.__host,self.__port, timeout=DD_TIMEOUT)
190
+ c.request('PUT',method,body,headers)
191
+ r = c.getresponse()
192
+ data = r.read()
193
+ except:
194
+ raise DDCommunicationError(u,"PUT",headers,body,r)
195
+ LOG(data)
196
+ try:
197
+ return self.__return_format(data)
198
+ except:
199
+ raise DDDataError(u,"PUT",headers,body,data)
200
+
201
+ def post(self,method,body):
202
+ """POST request to DeepDetect server"""
203
+
204
+ r = None
205
+ u = ""
206
+ headers = {}
207
+ try:
208
+ u = self.__ddurl + method
209
+ if self.__proto == self.__HTTP:
210
+ LOG("curl -X POST 'http://%s:%s%s' -d '%s'"%(self.__host,
211
+ self.__port,
212
+ method,
213
+ body))
214
+ c=httplib.HTTPConnection(self.__host,self.__port,timeout=DD_TIMEOUT)
215
+ else:
216
+ LOG("curl -k -X POST 'https://%s:%s%s' -d '%s'"%(self.__host,
217
+ self.__port,
218
+ method,
219
+ body))
220
+ c=httplib.HTTPSConnection(self.__host,self.__port, timeout=DD_TIMEOUT)
221
+ c.request('POST',method,body,headers)
222
+ r = c.getresponse()
223
+ data = r.read()
224
+
225
+ except:
226
+ raise DDCommunicationError(u,"POST",headers,body,r)
227
+
228
+ # LOG(data)
229
+ try:
230
+ return self.__return_format(data)
231
+ except:
232
+ import traceback
233
+ print (traceback.format_exc())
234
+
235
+ raise DDDataError(u,"POST",headers,body,data)
236
+
237
+ def delete(self, method):
238
+ """DELETE request to DeepDetect server"""
239
+
240
+ LOG("DELETE %s"%(method))
241
+ r = None
242
+ u = ""
243
+ body = ""
244
+ headers = {}
245
+ try:
246
+ u = self.__ddurl + method
247
+ if self.__proto == self.__HTTP:
248
+ c=httplib.HTTPConnection(self.__host,self.__port, timeout=DD_TIMEOUT)
249
+ else:
250
+ c=httplib.HTTPSConnection(self.__host,self.__port, timeout=DD_TIMEOUT)
251
+ c.request('DELETE',method,body,headers)
252
+ r = c.getresponse()
253
+ data = r.read()
254
+ except:
255
+ raise DDCommunicationError(u,"DELETE",headers,None,r)
256
+
257
+ LOG(data)
258
+ try:
259
+ return self.__return_format(data)
260
+ except:
261
+ raise DDDataError(u,"DELETE",headers,None,data)
262
+
263
+
264
+ # API methods
265
+
266
+ def info(self):
267
+ """Info on the DeepDetect server"""
268
+ return self.get(self.__urls["info"])
269
+
270
+
271
+ # - PUT services
272
+ # - GET services
273
+ # - DELETE services
274
+ def put_service(self,sname,model,description,mllib,parameters_input,parameters_mllib,parameters_output,mltype='supervised'):
275
+ """
276
+ Create a service
277
+ Parameters:
278
+ sname -- service name as a resource
279
+ model -- dict with model location and optional templates
280
+ description -- string describing the service
281
+ mllib -- ML library name, e.g. caffe
282
+ parameters_input -- dict of input parameters
283
+ parameters_mllib -- dict ML library parameters
284
+ parameters_output -- dict of output parameters
285
+ """
286
+ body={"description":description,"mllib":mllib,"type":mltype,
287
+ "parameters":{"input":parameters_input,"mllib":parameters_mllib,"output":parameters_output},
288
+ "model":model}
289
+ return self.put(self.__urls["services"] + '/%s'%sname,json.dumps(body))
290
+
291
+ def get_service(self,sname):
292
+ """
293
+ Get information about a service
294
+ Parameters:
295
+ sname -- service name as a resource
296
+ """
297
+ return self.get(self.__urls["services"] + '/%s'%sname)
298
+
299
+ def delete_service(self,sname,clear=None):
300
+ """
301
+ Delete a service
302
+ Parameters:
303
+ sname -- service name as a resource
304
+ clear -- 'full','lib' or 'mem', optionally clears model repository data
305
+ """
306
+ qs = self.__urls["services"] + '/%s'%sname
307
+ if clear:
308
+ qs += '?clear=' + clear
309
+ return self.delete(qs)
310
+
311
+
312
+ # PUT/POST /train
313
+ # GET /train
314
+ # DELETE /train
315
+
316
+ def post_train(self,sname,data,parameters_input,parameters_mllib,parameters_output,async=True):
317
+ """
318
+ Creates a training job
319
+ Parameters:
320
+ sname -- service name as a resource
321
+ async -- whether to run the job as non-blocking
322
+ data -- array of input data / dataset for training
323
+ parameters_input -- dict of input parameters
324
+ parameters_mllib -- dict ML library parameters
325
+ parameters_output -- dict of output parameters
326
+ """
327
+ body={"service":sname,"async":async,
328
+ "parameters":{"input":parameters_input,"mllib":parameters_mllib,"output":parameters_output},
329
+ "data":data}
330
+ return self.post(self.__urls["train"],json.dumps(body))
331
+
332
+ def get_train(self,sname,job=1,timeout=0,measure_hist=False):
333
+ """
334
+ Get information on a non-blocking training job
335
+ Parameters:
336
+ sname -- service name as a resource
337
+ job -- job number on the service
338
+ timeout -- timeout before obtaining the job status
339
+ measure_hist -- whether to return the full measure history (e.g. for plotting)
340
+ """
341
+ qs=self.__urls["train"] + "?service=" + sname + "&job=" + str(job) + "&timeout=" + str(timeout)
342
+ if measure_hist:
343
+ qs += "&parameters.output.measure_hist=true"
344
+ return self.get(qs)
345
+
346
+ def delete_train(self,sname,job=1):
347
+ """
348
+ Kills a non-blocking training job
349
+ Parameters:
350
+ sname -- service name as a resource
351
+ job -- job number on the service
352
+ """
353
+ qs=self.__urls["train"] + "?service=" + sname + "&job=" + str(job)
354
+ return self.delete(qs)
355
+
356
+
357
+ # POST /predict
358
+
359
+ def post_predict(self,sname,data,parameters_input,parameters_mllib,parameters_output):
360
+ """
361
+ Makes prediction from data and model
362
+ Parameters:
363
+ sname -- service name as a resource
364
+ data -- array of data URI to predict from
365
+ parameters_input -- dict of input parameters
366
+ parameters_mllib -- dict ML library parameters
367
+ parameters_output -- dict of output parameters
368
+ """
369
+ body={"service":sname,
370
+ "parameters":{"input":parameters_input,"mllib":parameters_mllib,"output":parameters_output},
371
+ "data":data}
372
+ return self.post(self.__urls["predict"],json.dumps(body))
373
+
374
+ # test
375
+ if __name__ == '__main__':
376
+ dd = DD()
377
+ dd.set_return_format(dd.RETURN_PYTHON)
378
+ inf = dd.info()
379
+ print (inf)