电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

5 分鐘讀懂Python 中的 Hook 鉤子函數(shù)

瀏覽:76日期:2022-07-02 17:40:39

5 分鐘讀懂Python 中的 Hook 鉤子函數(shù)

1. 什么是Hook

經(jīng)常會聽到鉤子函數(shù)(hook function)這個概念,最近在看目標(biāo)檢測開源框架mmdetection,里面也出現(xiàn)大量Hook的編程方式,那到底什么是hook?hook的作用是什么?

what is hook ?鉤子hook,顧名思義,可以理解是一個掛鉤,作用是有需要的時候掛一個東西上去。具體的解釋是:鉤子函數(shù)是把我們自己實(shí)現(xiàn)的hook函數(shù)在某一時刻掛接到目標(biāo)掛載點(diǎn)上。 hook函數(shù)的作用 舉個例子,hook的概念在windows桌面軟件開發(fā)很常見,特別是各種事件觸發(fā)的機(jī)制; 比如C++的MFC程序中,要監(jiān)聽鼠標(biāo)左鍵按下的時間,MFC提供了一個onLeftKeyDown的鉤子函數(shù)。很顯然,MFC框架并沒有為我們實(shí)現(xiàn)onLeftKeyDown具體的操作,只是為我們提供一個鉤子,當(dāng)我們需要處理的時候,只要去重寫這個函數(shù),把我們需要操作掛載在這個鉤子里,如果我們不掛載,MFC事件觸發(fā)機(jī)制中執(zhí)行的就是空的操作。

從上面可知

hook函數(shù)是程序中預(yù)定義好的函數(shù),這個函數(shù)處于原有程序流程當(dāng)中(暴露一個鉤子出來) 我們需要再在有流程中鉤子定義的函數(shù)塊中實(shí)現(xiàn)某個具體的細(xì)節(jié),需要把我們的實(shí)現(xiàn),掛接或者注冊(register)到鉤子里,使得hook函數(shù)對目標(biāo)可用 hook 是一種編程機(jī)制,和具體的語言沒有直接的關(guān)系 如果從設(shè)計(jì)模式上看,hook模式是模板方法的擴(kuò)展 鉤子只有注冊的時候,才會使用,所以原有程序的流程中,沒有注冊或掛載時,執(zhí)行的是空(即沒有執(zhí)行任何操作)

本文用python來解釋hook的實(shí)現(xiàn)方式,并展示在開源項(xiàng)目中hook的應(yīng)用案例。hook函數(shù)和我們常聽到另外一個名稱:回調(diào)函數(shù)(callback function)功能是類似的,可以按照同種模式來理解。

5 分鐘讀懂Python 中的 Hook 鉤子函數(shù)

2. hook實(shí)現(xiàn)例子

據(jù)我所知,hook函數(shù)最常使用在某種流程處理當(dāng)中。這個流程往往有很多步驟。hook函數(shù)常常掛載在這些步驟中,為增加額外的一些操作,提供靈活性。

下面舉一個簡單的例子,這個例子的目的是實(shí)現(xiàn)一個通用往隊(duì)列中插入內(nèi)容的功能。流程步驟有2個

需要再插入隊(duì)列前,對數(shù)據(jù)進(jìn)行篩選 input_filter_fn

插入隊(duì)列 insert_queue

class ContentStash(object): ''' content stash for online operation pipeline is 1. input_filter: filter some contents, no use to user 2. insert_queue(redis or other broker): insert useful content to queue ''' def __init__(self): self.input_filter_fn = None self.broker = [] def register_input_filter_hook(self, input_filter_fn): ''' register input filter function, parameter is content dict Args: input_filter_fn: input filter function Returns: ''' self.input_filter_fn = input_filter_fn def insert_queue(self, content): ''' insert content to queue Args: content: dict Returns: ''' self.broker.append(content) def input_pipeline(self, content, use=False): ''' pipeline of input for content stash Args: use: is use, defaul False content: dict Returns: ''' if not use: return # input filter if self.input_filter_fn: _filter = self.input_filter_fn(content) # insert to queue if not _filter: self.insert_queue(content) # test## 實(shí)現(xiàn)一個你所需要的鉤子實(shí)現(xiàn):比如如果content 包含time就過濾掉,否則插入隊(duì)列def input_filter_hook(content): ''' test input filter hook Args: content: dict Returns: None or content ''' if content.get(’time’) is None: return else: return content # 原有程序content = {’filename’: ’test.jpg’, ’b64_file’: '#test', ’data’: {'result': 'cat', 'probility': 0.9}}content_stash = ContentStash(’audit’, work_dir=’’) # 掛上鉤子函數(shù), 可以有各種不同鉤子函數(shù)的實(shí)現(xiàn),但是要主要函數(shù)輸入輸出必須保持原有程序中一致,比如這里是contentcontent_stash.register_input_filter_hook(input_filter_hook) # 執(zhí)行流程content_stash.input_pipeline(content)

3. hook在開源框架中的應(yīng)用

3.1 keras

在深度學(xué)習(xí)訓(xùn)練流程中,hook函數(shù)體現(xiàn)的淋漓盡致。

一個訓(xùn)練過程(不包括數(shù)據(jù)準(zhǔn)備),會輪詢多次訓(xùn)練集,每次稱為一個epoch,每個epoch又分為多個batch來訓(xùn)練。流程先后拆解成:

開始訓(xùn)練 訓(xùn)練一個epoch前 訓(xùn)練一個batch前 訓(xùn)練一個batch后 訓(xùn)練一個epoch后 評估驗(yàn)證集 結(jié)束訓(xùn)練

這些步驟是穿插在訓(xùn)練一個batch數(shù)據(jù)的過程中,這些可以理解成是鉤子函數(shù),我們可能需要在這些鉤子函數(shù)中實(shí)現(xiàn)一些定制化的東西,比如在訓(xùn)練一個epoch后我們要保存下訓(xùn)練的模型,在結(jié)束訓(xùn)練時用最好的模型執(zhí)行下測試集的效果等等。

keras中是通過各種回調(diào)函數(shù)來實(shí)現(xiàn)鉤子hook功能的。這里放一個callback的父類,定制時只要繼承這個父類,實(shí)現(xiàn)你過關(guān)注的鉤子就可以了。

@keras_export(’keras.callbacks.Callback’)class Callback(object): '''Abstract base class used to build new callbacks. Attributes: params: Dict. Training parameters (eg. verbosity, batch size, number of epochs...). model: Instance of `keras.models.Model`. Reference of the model being trained. The `logs` dictionary that callback methods take as argument will contain keys for quantities relevant to the current batch or epoch (see method-specific docstrings). ''' def __init__(self): self.validation_data = None # pylint: disable=g-missing-from-attributes self.model = None # Whether this Callback should only run on the chief worker in a # Multi-Worker setting. # TODO(omalleyt): Make this attr public once solution is stable. self._chief_worker_only = None self._supports_tf_logs = False def set_params(self, params): self.params = params def set_model(self, model): self.model = model @doc_controls.for_subclass_implementers @generic_utils.default def on_batch_begin(self, batch, logs=None): '''A backwards compatibility alias for `on_train_batch_begin`.''' @doc_controls.for_subclass_implementers @generic_utils.default def on_batch_end(self, batch, logs=None): '''A backwards compatibility alias for `on_train_batch_end`.''' @doc_controls.for_subclass_implementers def on_epoch_begin(self, epoch, logs=None): '''Called at the start of an epoch. Subclasses should override for any actions to run. This function should only be called during TRAIN mode. Arguments: epoch: Integer, index of epoch. logs: Dict. Currently no data is passed to this argument for this method but that may change in the future. ''' @doc_controls.for_subclass_implementers def on_epoch_end(self, epoch, logs=None): '''Called at the end of an epoch. Subclasses should override for any actions to run. This function should only be called during TRAIN mode. Arguments: epoch: Integer, index of epoch. logs: Dict, metric results for this training epoch, and for the validation epoch if validation is performed. Validation result keys are prefixed with `val_`. ''' @doc_controls.for_subclass_implementers @generic_utils.default def on_train_batch_begin(self, batch, logs=None): '''Called at the beginning of a training batch in `fit` methods. Subclasses should override for any actions to run. Arguments: batch: Integer, index of batch within the current epoch. logs: Dict, contains the return value of `model.train_step`. Typically, the values of the `Model`’s metrics are returned. Example: `{’loss’: 0.2, ’accuracy’: 0.7}`. ''' # For backwards compatibility. self.on_batch_begin(batch, logs=logs) @doc_controls.for_subclass_implementers @generic_utils.default def on_train_batch_end(self, batch, logs=None): '''Called at the end of a training batch in `fit` methods. Subclasses should override for any actions to run. Arguments: batch: Integer, index of batch within the current epoch. logs: Dict. Aggregated metric results up until this batch. ''' # For backwards compatibility. self.on_batch_end(batch, logs=logs) @doc_controls.for_subclass_implementers @generic_utils.default def on_test_batch_begin(self, batch, logs=None): '''Called at the beginning of a batch in `evaluate` methods. Also called at the beginning of a validation batch in the `fit` methods, if validation data is provided. Subclasses should override for any actions to run. Arguments: batch: Integer, index of batch within the current epoch. logs: Dict, contains the return value of `model.test_step`. Typically, the values of the `Model`’s metrics are returned. Example: `{’loss’: 0.2, ’accuracy’: 0.7}`. ''' @doc_controls.for_subclass_implementers @generic_utils.default def on_test_batch_end(self, batch, logs=None): '''Called at the end of a batch in `evaluate` methods. Also called at the end of a validation batch in the `fit` methods, if validation data is provided. Subclasses should override for any actions to run. Arguments: batch: Integer, index of batch within the current epoch. logs: Dict. Aggregated metric results up until this batch. ''' @doc_controls.for_subclass_implementers @generic_utils.default def on_predict_batch_begin(self, batch, logs=None): '''Called at the beginning of a batch in `predict` methods. Subclasses should override for any actions to run. Arguments: batch: Integer, index of batch within the current epoch. logs: Dict, contains the return value of `model.predict_step`, it typically returns a dict with a key ’outputs’ containing the model’s outputs. ''' @doc_controls.for_subclass_implementers @generic_utils.default def on_predict_batch_end(self, batch, logs=None): '''Called at the end of a batch in `predict` methods. Subclasses should override for any actions to run. Arguments: batch: Integer, index of batch within the current epoch. logs: Dict. Aggregated metric results up until this batch. ''' @doc_controls.for_subclass_implementers def on_train_begin(self, logs=None): '''Called at the beginning of training. Subclasses should override for any actions to run. Arguments: logs: Dict. Currently no data is passed to this argument for this method but that may change in the future. ''' @doc_controls.for_subclass_implementers def on_train_end(self, logs=None): '''Called at the end of training. Subclasses should override for any actions to run. Arguments: logs: Dict. Currently the output of the last call to `on_epoch_end()` is passed to this argument for this method but that may change in the future. ''' @doc_controls.for_subclass_implementers def on_test_begin(self, logs=None): '''Called at the beginning of evaluation or validation. Subclasses should override for any actions to run. Arguments: logs: Dict. Currently no data is passed to this argument for this method but that may change in the future. ''' @doc_controls.for_subclass_implementers def on_test_end(self, logs=None): '''Called at the end of evaluation or validation. Subclasses should override for any actions to run. Arguments: logs: Dict. Currently the output of the last call to `on_test_batch_end()` is passed to this argument for this method but that may change in the future. ''' @doc_controls.for_subclass_implementers def on_predict_begin(self, logs=None): '''Called at the beginning of prediction. Subclasses should override for any actions to run. Arguments: logs: Dict. Currently no data is passed to this argument for this method but that may change in the future. ''' @doc_controls.for_subclass_implementers def on_predict_end(self, logs=None): '''Called at the end of prediction. Subclasses should override for any actions to run. Arguments: logs: Dict. Currently no data is passed to this argument for this method but that may change in the future. ''' def _implements_train_batch_hooks(self): '''Determines if this Callback should be called for each train batch.''' return (not generic_utils.is_default(self.on_batch_begin) or not generic_utils.is_default(self.on_batch_end) or not generic_utils.is_default(self.on_train_batch_begin) or not generic_utils.is_default(self.on_train_batch_end))

這些鉤子的原始程序是在模型訓(xùn)練流程中的

keras源碼位置: tensorflowpythonkerasenginetraining.py

部分摘錄如下(## I am hook):

# Container that configures and calls `tf.keras.Callback`s. if not isinstance(callbacks, callbacks_module.CallbackList): callbacks = callbacks_module.CallbackList( callbacks, add_history=True, add_progbar=verbose != 0, model=self, verbose=verbose, epochs=epochs, steps=data_handler.inferred_steps) ## I am hook callbacks.on_train_begin() training_logs = None # Handle fault-tolerance for multi-worker. # TODO(omalleyt): Fix the ordering issues that mean this has to # happen after `callbacks.on_train_begin`. data_handler._initial_epoch = ( # pylint: disable=protected-access self._maybe_load_initial_epoch_from_ckpt(initial_epoch)) for epoch, iterator in data_handler.enumerate_epochs(): self.reset_metrics() callbacks.on_epoch_begin(epoch) with data_handler.catch_stop_iteration(): for step in data_handler.steps(): with trace.Trace(’TraceContext’,graph_type=’train’,epoch_num=epoch,step_num=step,batch_size=batch_size): ## I am hook callbacks.on_train_batch_begin(step) tmp_logs = train_function(iterator) if data_handler.should_sync:context.async_wait() logs = tmp_logs # No error, now safe to assign to logs. end_step = step + data_handler.step_increment callbacks.on_train_batch_end(end_step, logs) epoch_logs = copy.copy(logs) # Run validation. ## I am hook callbacks.on_epoch_end(epoch, epoch_logs)

3.2 mmdetection

mmdetection是一個目標(biāo)檢測的開源框架,集成了許多不同的目標(biāo)檢測深度學(xué)習(xí)算法(pytorch版),如faster-rcnn, fpn, retianet等。里面也大量使用了hook,暴露給應(yīng)用實(shí)現(xiàn)流程中具體部分。

詳見https://github.com/open-mmlab/mmdetection

這里看一個訓(xùn)練的調(diào)用例子(摘錄)https://github.com/open-mmlab/mmdetection/blob/5d592154cca589c5113e8aadc8798bbc73630d98/mmdet/apis/train.py

def train_detector(model, dataset, cfg, distributed=False, validate=False, timestamp=None, meta=None): logger = get_root_logger(cfg.log_level) # prepare data loaders # put model on gpus # build runner optimizer = build_optimizer(model, cfg.optimizer) runner = EpochBasedRunner( model, optimizer=optimizer, work_dir=cfg.work_dir, logger=logger, meta=meta) # an ugly workaround to make .log and .log.json filenames the same runner.timestamp = timestamp # fp16 setting # register hooks runner.register_training_hooks(cfg.lr_config, optimizer_config, cfg.checkpoint_config, cfg.log_config, cfg.get(’momentum_config’, None)) if distributed: runner.register_hook(DistSamplerSeedHook()) # register eval hooks if validate: # Support batch_size > 1 in validation eval_cfg = cfg.get(’evaluation’, {}) eval_hook = DistEvalHook if distributed else EvalHook runner.register_hook(eval_hook(val_dataloader, **eval_cfg)) # user-defined hooks if cfg.get(’custom_hooks’, None): custom_hooks = cfg.custom_hooks assert isinstance(custom_hooks, list), f’custom_hooks expect list type, but got {type(custom_hooks)}’ for hook_cfg in cfg.custom_hooks: assert isinstance(hook_cfg, dict), ’Each item in custom_hooks expects dict type, but got ’ f’{type(hook_cfg)}’ hook_cfg = hook_cfg.copy() priority = hook_cfg.pop(’priority’, ’NORMAL’) hook = build_from_cfg(hook_cfg, HOOKS) runner.register_hook(hook, priority=priority)

4. 總結(jié)

本文介紹了hook的概念和應(yīng)用,并給出了python的實(shí)現(xiàn)細(xì)則。希望對比有幫助??偨Y(jié)如下:

hook函數(shù)是流程中預(yù)定義好的一個步驟,沒有實(shí)現(xiàn) 掛載或者注冊時, 流程執(zhí)行就會執(zhí)行這個鉤子函數(shù) 回調(diào)函數(shù)和hook函數(shù)功能上是一致的 hook設(shè)計(jì)方式帶來靈活性,如果流程中有一個步驟,你想讓調(diào)用方來實(shí)現(xiàn),你可以用hook函數(shù)

到此這篇關(guān)于5 分鐘讀懂Python 中的 Hook 鉤子函數(shù)的文章就介紹到這了,更多相關(guān)Python Hook 鉤子函數(shù)內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 双相钢_双相不锈钢_双相钢圆钢棒_双相不锈钢报价「海新双相钢」 双能x射线骨密度检测仪_dxa骨密度仪_双能x线骨密度仪_品牌厂家【品源医疗】 | 聚丙烯酰胺_阴离子_阳离子「用量少」巩义亿腾厂家直销,售后无忧 聚合甘油__盐城市飞龙油脂有限公司 | 广东机电安装工程_中央空调工程_东莞装饰装修-广东粤标建设有限公司 | 高中学习网-高考生信息学习必备平台 | 石牌坊价格石牌坊雕刻制作_石雕牌坊牌楼石栏杆厂家_山东嘉祥石雕有限公司 | DDoS安全防护官网-领先的DDoS安全防护服务商 | 【黄页88网】-B2B电子商务平台,b2b平台免费发布信息网 | 无味渗透剂,泡沫抑尘剂,烷基糖苷-威海威能化工有限公司 | 广东恩亿梯电源有限公司【官网】_UPS不间断电源|EPS应急电源|模块化机房|电动汽车充电桩_UPS电源厂家(恩亿梯UPS电源,UPS不间断电源,不间断电源UPS) | 培训中心-翰香原香酥板栗饼加盟店总部-正宗板栗酥饼技术 | 真空搅拌机-行星搅拌机-双行星动力混合机-广州市番禺区源创化工设备厂 | 上海刑事律师|刑事辩护律师|专业刑事犯罪辩护律师免费咨询-[尤辰荣]金牌上海刑事律师团队 | 驾驶式洗地机/扫地机_全自动洗地机_工业洗地机_荣事达工厂官网 | 半自动预灌装机,卡式瓶灌装机,注射器灌装机,给药器灌装机,大输液灌装机,西林瓶灌装机-长沙一星制药机械有限公司 | 对照品_中药对照品_标准品_对照药材_「格利普」高纯中药标准品厂家-成都格利普生物科技有限公司 澳门精准正版免费大全,2025新澳门全年免费,新澳天天开奖免费资料大全最新,新澳2025今晚开奖资料,新澳马今天最快最新图库 | DWS物流设备_扫码称重量方一体机_快递包裹分拣机_广东高臻智能装备有限公司 | X光检测仪_食品金属异物检测机_X射线检测设备_微现检测 | 仿古瓦,仿古金属瓦,铝瓦,铜瓦,铝合金瓦-西安东申景观艺术工程有限公司 | 上海办公室装修公司_办公室设计_直营办公装修-羚志悦装 | 便携式表面粗糙度仪-彩屏硬度计-分体式粗糙度仪-北京凯达科仪科技有限公司 | 标准品网_标准品信息网_【中检计量】 | 欧美日韩国产一区二区三区不_久久久久国产精品无码不卡_亚洲欧洲美洲无码精品AV_精品一区美女视频_日韩黄色性爱一级视频_日本五十路人妻斩_国产99视频免费精品是看4_亚洲中文字幕无码一二三四区_国产小萍萍挤奶喷奶水_亚洲另类精品无码在线一区 | 污水提升器,污水提升泵,污水提升装置-德国泽德(zehnder)水泵系统有限公司 | 耐高温风管_耐高温软管_食品级软管_吸尘管_钢丝软管_卫生级软管_塑料波纹管-东莞市鑫翔宇软管有限公司 | 南方珠江-南方一线电缆-南方珠江科技电缆-南方珠江科技有限公司 南汇8424西瓜_南汇玉菇甜瓜-南汇水蜜桃价格 | 立刷【微电签pos机】-嘉联支付立刷运营中心| 全球化工设备网—化工设备,化工机械,制药设备,环保设备的专业网络市场。 | 工控机-工业平板电脑-研华工控机-研越无风扇嵌入式box工控机 | 楼承板-钢筋楼承板-闭口楼承板-无锡优贝斯楼承板厂 | 混合反应量热仪-高温高压量热仪-微机差热分析仪DTA|凯璞百科 | 全自动贴标机-套标机-工业热风机-不干胶贴标机-上海厚冉机械 | 澳门精准正版免费大全,2025新澳门全年免费,新澳天天开奖免费资料大全最新,新澳2025今晚开奖资料,新澳马今天最快最新图库-首页-东莞市傲马网络科技有限公司 | 石家庄小程序开发_小程序开发公司_APP开发_网站制作-石家庄乘航网络科技有限公司 | 干洗店加盟_洗衣店加盟_干洗店设备-伊蔻干洗「武汉总部」 | 月嫂_保姆_育婴_催乳_母婴护理_产后康复_养老护理-吉祥到家家政 硫酸亚铁-聚合硫酸铁-除氟除磷剂-复合碳源-污水处理药剂厂家—长隆科技 | 水轮机密封网 | 水轮机密封产品研发生产厂家 | 亚克隆,RNAi干扰检测,miRNA定量检测-上海基屹生物科技有限公司 | 首页|光催化反应器_平行反应仪_光化学反应仪-北京普林塞斯科技有限公司 | 齿轮减速电机一体机_蜗轮蜗杆减速马达-德国BOSERL齿轮减速机带电机生产厂家 | 济南货架定做_仓储货架生产厂_重型货架厂_仓库货架批发_济南启力仓储设备有限公司 | 硬度计_影像测量仪_维氏硬度计_佛山市精测计量仪器设备有限公司厂家 |