ó šÄïYc@sødZddlZddlmZmZmZddlmZddlmZddlmZ dd l m Z m Z m Z dd lmZd efd „ƒYZd „Zd„Zdefd„ƒYZdefd„ƒYZdefd„ƒYZdS(s3Base container class for all neural network models.iÿÿÿÿNi(tsymboltndarrayt initializer(tSymbol(tNDArray(tnamei(t Parametert ParameterDicttDeferredInitializationError(t_indentt _BlockScopecBs>eZdZdZd„Zed„ƒZd„Zd„Z RS(s$Scope for collecting child `Block`s.cCs(||_i|_d|_d|_dS(N(t_blockt_countertNonet _old_scopet _name_scope(tselftblock((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyt__init__$s   cCstj}|dkrw|dkr@tjjjd|ƒd}n|dkr[t|ƒ}nt|j|ƒ}||fS|dkr¼|j j|dƒ}d||f}|d|j |tj|_|t_tj|jjƒ|_|jjƒ|S(N( R RRRtPrefixR RRt __enter__(R((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyR!Bs    cCs/|jj|||ƒd|_|jt_dS(N(Rt__exit__R RR R(Rtptypetvaluettrace((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyR"Is N( t__name__t __module__t__doc__R RRt staticmethodRR!R"(((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyR s   cCsþt|tƒr"|gtdƒfSt|tƒrnt|jƒƒ}|dkrU|nd}|gt|ƒfSt|ttfƒs«tdt |ƒt t |ƒƒfƒ‚g}g}x:|D]2}t |ƒ\}}|j |ƒ|j |ƒq¾W||fS(NiisSHybridBlock input must be (nested) list of Symbol or NDArray, but got %s of type %s(t isinstanceRtintRtlent list_outputstlistttupletAssertionErrortstrttypet_flattentextendtappend(targstlengthtflattfmtstitargtfmt((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyR3Os "  cCs¿t|tƒr?|dkr-|d|dfS|| ||fSt|ttfƒs|tdt|ƒtt|ƒƒfƒ‚g}x0|D](}t||ƒ\}}|j|ƒq‰W||fS(NiisTHybridBlock output must be (nested) list of Symbol or NDArray, but got %s of type %s( R*R+R.R/R0R1R2t_regroupR5(R6R<tretR:tres((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyR=cs " tBlockcBsÎeZdZddd„Zd„Zd„Zd„Zed„ƒZ ed„ƒZ d„Z ed„ƒZ d „Z d „Zeed „Zd „Zejƒded „Zed„Zd„Zd„ZRS(snBase class for all neural network layers and models. Your models should subclass this class. `Block` can be nested recursively in a tree structure. You can create and assign child `Block` as regular attributes:: from mxnet.gluon import Block, nn from mxnet import ndarray as F class Model(Block): def __init__(self, **kwargs): super(Model, self).__init__(**kwargs) # use name_scope to give child Blocks appropriate names. # It also allows sharing Parameters between Blocks recursively. with self.name_scope(): self.dense0 = nn.Dense(20) self.dense1 = nn.Dense(20) def forward(self, x): x = F.relu(self.dense0(x)) return F.relu(self.dense1(x)) model = Model() model.initialize(ctx=mx.cpu(0)) model(F.zeros((10, 10), ctx=mx.cpu(0))) Child `Block` assigned this way will be registered and `collect_params` will collect their Parameters recursively. Parameters ---------- prefix : str Prefix acts like a name space. It will be prepended to the names of all Parameters and child `Block`s in this `Block`'s `name_scope`. Prefix should be unique within one model to prevent name collisions. params : ParameterDict or None `ParameterDict` for sharing weights with the new `Block`. For example, if you want `dense1` to share `dense0`'s weights, you can do:: dense0 = nn.Dense(20) dense1 = nn.Dense(20, params=dense0.collect_params()) cCsntj|||jƒƒ\|_|_|jjdƒrF|jd n|j|_t|ƒ|_g|_dS(NRiÿÿÿÿ( R Rt_aliast_prefixt_paramstendswithRt_scopet _children(RRR((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRŸs'+c Csƒd}djg|jjƒD]B\}}t|tƒrdjd|dt|jƒdƒƒ^qƒ}|jd|jj d|ƒS( Ns{name}( {modstr} )s s ({key}): {block}tkeyRiRtmodstr( tjoint__dict__titemsR*R@tformatR t__repr__t __class__R&(RtsRGRRH((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRM¥s  XcCs<tt|ƒj||ƒt|tƒr8|j|ƒndS(sRegisters parameters.N(tsuperR@t __setattr__R*tregister_child(RRR$((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRQ­scCs|jjjƒS(N(RNR&tlower(R((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRA³scCs|jS(sPrefix of this `Block`.(RB(R((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyR¶scCs|jS(s-Name of this `Block`, without '_' in the end.(R(R((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyR»scCs|jS(sÔReturns a name space object managing a child `Block` and parameter names. Should be used within a `with` statement:: with self.name_scope(): self.dense = nn.Dense(20) (RE(R((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyt name_scopeÀscCs|jS(saReturns this `Block`'s parameter dictionary (does not include its children's parameters).(RC(R((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRÉscCsMt|jjƒ}|j|jƒx$|jD]}|j|jƒƒq,W|S(s_Returns a `ParameterDict` containing this `Block` and all of its children's Parameters.(RRCRtupdateRRFtcollect_params(RR>tcld((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRVÏs cCs |jƒj|d|jƒdS(sSSave parameters to file. filename : str Path to file. t strip_prefixN(RVtsaveR(Rtfilename((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyt save_paramsØscCs&|jƒj|||||jƒdS(sÛLoad parameters from file. filename : str Path to parameter file. ctx : Context or list of Context Context(s) initialize loaded parameters on. allow_missing : bool, default False Whether to silently skip loading parameters not represents in the file. ignore_extra : bool, default False Whether to silently ignore parameters from the file that are not present in this Block. N(RVtloadR(RRZtctxt allow_missingt ignore_extra((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyt load_paramsàscCs|jj|ƒdS(suRegisters block as a child of self. `Block`s assigned to self as attributes will be registered automatically.N(RFR5(RR((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRRòscCs|jƒj|||ƒdS(sƒInitializes `Parameter`s of this `Block` and its children. Equivalent to `block.collect_params().initialize(...)` N(RVt initialize(RtinitR]tverbose((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRa÷scCs%x|jD]}|j|ƒq WdS(säActivates or deactivates `HybridBlock`s recursively. Has no effect on non-hybrid children. Parameters ---------- active : bool, default True Whether to turn hybrid on or off. N(RFt hybridize(RtactiveRW((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRdþs cGs |j|ŒS(s1Calls forward. Only accepts positional arguments.(tforward(RR6((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyt__call__ scGs t‚dS(sÑOverrides to implement forward computation using `NDArray`. Only accepts positional arguments. Parameters ---------- *args : list of NDArray Input tensors. N(tNotImplementedError(RR6((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRfs N(R&R'R(R RRMRQRAtpropertyRRRTRRVR[tFalseR`RRRtUniformRatTrueRdRgRf(((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyR@ss$+        t HybridBlockcBsqeZdZd d d„Zd„Zd„Zed„Zd„Z d„Z d„Z d„Z d „Z d „ZRS( s<`HybridBlock` supports forwarding with both Symbol and NDArray. Forward computation in `HybridBlock` must be static to work with `Symbol`s, i.e. you cannot call `.asnumpy()`, `.shape`, `.dtype`, etc on tensors. Also, you cannot use branching or loop logic that bases on non-constant expressions like random numbers or intermediate results, since they change the graph structure for each iteration. Before activating with `hybridize()`, `HybridBlock` works just like normal `Block`. After activation, `HybridBlock` will create a symbolic graph representing the forward computation and cache it. On subsequent forwards, the cached graph will be used instead of `hybrid_forward`. Refer `Hybrid tutorial `_ to see the end-to-end usage. cCsbtt|ƒjd|d|ƒi|_d|_d|_d|_d|_d|_ t |_ dS(NRR(( RPRmRt _reg_paramst _cached_graphR t _cached_opt_cached_paramst _out_formatt _in_formatRjt_active(RRR((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyR,s      cCsntt|ƒj||ƒt|tƒrj||jksZt|j|tƒ sZtdƒ‚||j|Ts (RoR3RstrangeR,RRvR=RnRKRTthybrid_forwardRrtGroup(RR6R:tinputstgrouped_inputsRtout((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyt _get_graphNs 2 c GsÈ|j|Œ\}}t|ƒ\}}|jd„t||ƒDƒ\}}}d„t|jƒ|ƒDƒ}|jd„t|jƒ|ƒDƒƒx*|jƒjƒD]}||j |_ qªWdS(s'Infers shape of Parameters from inputs.cSs%i|]\}}|j|j“qS((tshapeR(RwR:Rx((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pys bs cSsi|]\}}||“qS(((RwR:Rx((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pys cs cSsi|]\}}||“qS(((RwRR€((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pys ds N( RR3t infer_shapetziptlist_argumentsRUtlist_auxiliary_statesRVtvaluesRR€( RR6R|R~Rt arg_shapest aux_shapestsdictR:((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyR]s% cGs|j|Œ\}}tj|ƒ|_t|jƒjƒƒ}g|jƒD]}|j|dƒ^qL|_ t |ƒt |j dƒt |jƒƒks¨t dƒ‚d„t|ƒDƒ}gt|jƒƒD](\}}||krÑ|||f^qÑ|_dS(NisWrong number of inputs.cSs"i|]\}}||j“qS((R(RwR:Rv((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pys rs (RRtCachedOpRptdictRVRKt list_inputsRR RqR,RoR0t enumeratet_in_idx(RR6R|R~RRtname2posR:((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyt _build_cacheis.2 cGs`|jdkr|j|Œny2g|jD]}|rD|jƒnd^q,}Wnytk rÌ|j|Œx*|jD]}|dk rx|jƒqxqxWg|jD]}|r½|jƒnd^q¥}nXt|ƒ\}}||j ksút dƒ‚x%|j D]\}}||||”s cs(i|]\}}|jˆƒ|“qS((R(RwR:Rx(R](s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pys ™s NsZHybridBlock requires the first argument to forward be either Symbol or NDArray, but got %scSs%i|]\}}|jƒ|“qS((Rv(RwR:Rx((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pys Ÿs (R*RtcontextRtR“RnRKRRRVR…R‘RzRRR0R2RTR(RtxR6RR:((R]s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRfŒs$  # # cOs t‚dS(sOverrides to construct symbolic graph for this `Block`. Parameters ---------- x : Symbol or NDArray The first input tensor. *args : list of Symbol or list of NDArray Additional input tensors. N(Rh(RtFR•R6tkwargs((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRz£s N(R&R'R(R RRQRRRlRdRRRR“RfRz(((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRms    t SymbolBlockcBs,eZdZdd„Zd„Zd„ZRS(smConstruct block from symbol. This is useful for using pre-trained models as feature extractors. For example, you may want to extract get the output from fc2 layer in AlexNet. Parameters ---------- outputs : Symbol or list of Symbol The desired output for SymbolBlock. inputs : Symbol or list of Symbol The Variables in output's argument that should be used as inputs. params : ParameterDict Parameter dictionary for arguments and auxililary states of outputs that are not inputs. Examples -------- >>> # To extract the feature from fc1 and fc2 layers of AlexNet: >>> alexnet = gluon.model_zoo.vision.alexnet(pretrained=True, ctx=mx.cpu(), prefix='model_') >>> inputs = mx.sym.var('data') >>> out = alexnet(inputs) >>> internals = out.get_internals() >>> print(internals.list_outputs()) ['data', ..., 'model_dense0_relu_fwd_output', ..., 'model_dense1_relu_fwd_output', ...] >>> outputs = [internals['model_dense0_relu_fwd_output'], internals['model_dense1_relu_fwd_output']] >>> # Create SymbolBlock that shares parameters with alexnet >>> feat_model = gluon.SymbolBlock(outputs, inputs, params=alexnet.collect_params()) >>> x = mx.nd.random_normal(shape=(16, 3, 224, 224)) >>> print(feat_model(x)) cCsØtt|ƒjddddƒd|_td|ƒ|_t|tj ƒrpt |j ƒƒdkrp|g}nt|tj ƒr¦t |j ƒƒdkr¦|g}nt |ƒ\}|_ t |ƒ\}|_tj|ƒ}tƒ}xR|D]J}t |jƒj ƒƒdks)tdt|ƒƒ‚|j|jƒqïWx9|jƒD]+}||krJ|jj|dtƒqJqJWx?|jƒD]1}||kr†|jj|dddtƒq†q†W||f|_|jƒdS( NRRtis@Input symbols must be variable, but %s is an output of operatorstallow_deferred_inittgrad_reqtnull(RPR˜RR RBRRCR*RRR,R-R3RsRrR{tsett get_internalsR0R1taddRRƒRRRlR„RoR(RtoutputsR|RtsymsR~t input_namesR:((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRÑs. * *   !  #cGsât|tƒr2|j|j||ŒSWdQXnt|tƒsWtdt|ƒƒ‚t|gt|ƒƒ\}}||j ks‘tdƒ‚t j |j dƒ}|j d„t |j d|ƒDƒt||jƒdS(NsZHybridBlock requires the first argument to forward be either Symbol or NDArray, but got %ssInvalid input formaticSs"i|]\}}||j“qS((R(Rwtktv((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pys ús i(R*RR”R“RR0R2R3R.RstcopyRot_composeR‚R=Rr(RR•R6tin_fmtR>((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRfïs 'cOs t‚dS(N(Rh(RR–R•R6R—((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyRzýsN(R&R'R(R RRfRz(((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyR˜±s  (R(R¥R™RRRRRRRt parameterRRRtutilsR tobjectR R3R=R@RmR˜(((s1build/bdist.linux-armv7l/egg/mxnet/gluon/block.pyts /  ¨–