blob: d25a465a6287c3560252215ff2a3457713edde64 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import numpy as np
import json
import utils
import math
import sys
from six.moves import xrange
def calc_complexity(ishape, node):
y, x = map(int, eval(node['param']['kernel']))
N = int(node['param']['num_filter'])
C, Y, X = ishape
return x*(N+C)*X*Y, x*y*N*C*X*Y
def calc_eigenvalue(model, node):
W = model.arg_params[node['name'] + '_weight'].asnumpy()
N, C, y, x = W.shape
W = W.transpose((1,2,0,3)).reshape((C*y, -1))
U, D, Q = np.linalg.svd(W, full_matrices=False)
return D
def get_ranksel(model, ratio):
conf = json.loads(model.symbol.tojson())
_, output_shapes, _ = model.symbol.get_internals().infer_shape(data=(1,3,224,224))
out_names = model.symbol.get_internals().list_outputs()
out_shape_dic = dict(zip(out_names, output_shapes))
nodes = conf['nodes']
nodes = utils.topsort(nodes)
C = []
D = []
S = []
conv_names = []
EC = 0
for node in nodes:
if node['op'] == 'Convolution':
input_nodes = [nodes[int(j[0])] for j in node['inputs']]
data = [input_node for input_node in input_nodes\
if not input_node['name'].startswith(node['name'])][0]
if utils.is_input(data):
ishape = (3, 224, 224)
else:
ishape = out_shape_dic[data['name'] + '_output'][1:]
C.append(calc_complexity(ishape, node))
D.append(int(node['param']['num_filter']))
S.append(calc_eigenvalue(model, node))
conv_names.append(node['name'])
EC += C[-1][1]
for s in S:
ss = sum(s)
for i in xrange(1, len(s)):
s[i] += s[i-1]
n = len(C)
EC /= ratio
dp = [{}, {}]
dpc = [{} for _ in xrange(n)]
now, nxt = 0, 1
dp[now][0] = 0
for i in xrange(n):
dp[nxt] = {}
sys.stdout.flush()
for now_c, now_v in dp[now].items():
for d in xrange(min(len(S[i]), D[i])):
nxt_c = now_c + (d+1)*C[i][0]
if nxt_c > EC:
continue
nxt_v = dp[now][now_c] + math.log(S[i][d])
if nxt_c in dp[nxt]:
if nxt_v > dp[nxt][nxt_c]:
dp[nxt][nxt_c] = nxt_v
dpc[i][nxt_c] = (d,now_c)
else:
dp[nxt][nxt_c] = nxt_v
dpc[i][nxt_c] = (d,now_c)
now, nxt = nxt, now
maxv = -1e9
target_c = 0
for c,v in dp[now].items():
assert c <= EC, 'False'
if v > maxv:
maxv = v
target_c = c
res = [0]*n
nowc = target_c
for i in xrange(n-1,-1,-1):
res[i] = dpc[i][nowc][0] + 1
nowc = dpc[i][nowc][1]
return dict(zip(conv_names, res))