From 8c74590a370309bd2794172b6c5715d3629590f7 Mon Sep 17 00:00:00 2001 From: Gene Date: Fri, 7 Apr 2023 10:40:44 +0800 Subject: [PATCH 1/4] [MNT] Add the pipeline --- examples/example_market_db/example_db.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/examples/example_market_db/example_db.py b/examples/example_market_db/example_db.py index 4d8b3cf..a03feb7 100644 --- a/examples/example_market_db/example_db.py +++ b/examples/example_market_db/example_db.py @@ -1,4 +1,4 @@ -from learnware.market import EasyMarket +from learnware.market import EasyMarket, BaseUserInfo from learnware.market import database_ops from learnware.learnware import Learnware import learnware.specification as specification @@ -58,9 +58,19 @@ def test_market(): def test_search(): easy_market = EasyMarket() - # learnware_list = easy_market + for i in range(10): + user_spec = specification.rkme.RKMEStatSpecification() + user_spec.load(f"./learnware_pool/svm{i}/spec.json") + user_info = BaseUserInfo(id="user_0", semantic_spec={"desc": "test_user_number_0"}, stat_info={"RKME": user_spec}) + sorted_dist_list, single_learnware_list, mixture_learnware_list = easy_market.search_learnware(user_info) + + print(f"search result of user{i}:") + for dist, learnware in zip(sorted_dist_list, single_learnware_list): + print(f"dist: {dist}, learnware_id: {learnware.id}, learnware_name: {learnware.name}") + mixture_id = " ".join([learnware.id for learnware in mixture_learnware_list]) + print(f"mixture_learnware: {mixture_id}\n") if __name__ == "__main__": - # test_market() + test_market() test_search() From de97a6624bd29d0933b11a8e7756bb71ebf34795 Mon Sep 17 00:00:00 2001 From: Gene Date: Fri, 7 Apr 2023 10:46:45 +0800 Subject: [PATCH 2/4] [MNT] Modify the pipeline --- learnware/learnware/base.py | 4 ++-- learnware/market/easy.py | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/learnware/learnware/base.py b/learnware/learnware/base.py index 4500c71..8578f91 100644 --- a/learnware/learnware/base.py +++ b/learnware/learnware/base.py @@ -29,7 +29,7 @@ class Learnware: Raises ------ TypeError - The type of model must be dict or BaseModel, else raise error + The type of model must be str or BaseModel, else raise error """ if isinstance(model, BaseModel): return model @@ -42,7 +42,7 @@ class Learnware: model_module = get_module_by_module_path(model_dict["module_path"]) return getattr(model_module, model_dict["class_name"])() else: - raise TypeError("model must be BaseModel or dict") + raise TypeError("model must be BaseModel or str") def predict(self, X: np.ndarray) -> np.ndarray: return self.model.predict(X) diff --git a/learnware/market/easy.py b/learnware/market/easy.py index 8fa78ae..a752081 100644 --- a/learnware/market/easy.py +++ b/learnware/market/easy.py @@ -153,7 +153,7 @@ class EasyMarket(BaseMarket): # else: weight = torch.linalg.inv(K + torch.eye(K.shape[0]).to(user_rkme.device) * 1e-5) @ C - term1 = user_rkme.eval_Phi(user_rkme) + term1 = user_rkme.inner_prod(user_rkme) term2 = weight.T @ C term3 = weight.T @ K @ weight score = float(term1 - 2 * term2 + term3) @@ -274,7 +274,10 @@ class EasyMarket(BaseMarket): for RKME in RKME_list: mmd_dist = RKME.dist(user_rkme) mmd_dist_list.append(mmd_dist) - sorted_dist_list, sorted_learnware_list = (list(t) for t in zip(*sorted(zip(mmd_dist_list, learnware_list)))) + + sorted_idx_list = sorted(range(len(learnware_list)), key=lambda k: mmd_dist_list[k]) + sorted_dist_list = [mmd_dist_list[idx] for idx in sorted_idx_list] + sorted_learnware_list = [learnware_list[idx] for idx in sorted_idx_list] return sorted_dist_list, sorted_learnware_list @@ -304,9 +307,32 @@ class EasyMarket(BaseMarket): learnware_list = [self.learnware_list[key] for key in self.learnware_list] return learnware_list - def search_learnware(self, user_info: BaseUserInfo) -> Tuple[Any, List[Learnware]]: + def search_learnware(self, user_info: BaseUserInfo, search_num=3) -> Tuple[List[float], List[Learnware], List[Learnware]]: + """Search learnwares based on user_info + + Parameters + ---------- + user_info : BaseUserInfo + user_info contains semantic_spec and stat_info + search_num : int + The number of the returned learnwares + + Returns + ------- + Tuple[List[float], List[Learnware], List[float], List[Learnware]] + the first is the sorted list of rkme dist + the second is the sorted list of Learnware (single) by the rkme dist + the third is the list of Learnware (mixture), the size is search_num + """ learnware_list = self._search_by_semantic_spec(user_info) - return learnware_list + + if "RKME" not in user_info.stat_info: + return None, learnware_list, None + else: + user_rkme = user_info.stat_info["RKME"] + sorted_dist_list, single_learnware_list = self._search_by_rkme_spec_single(learnware_list, user_rkme) + weight_list, mixture_learnware_list = self._search_by_rkme_spec_mixture(learnware_list, user_rkme, search_num) + return sorted_dist_list, single_learnware_list, mixture_learnware_list def delete_learnware(self, id: str) -> bool: if not id in self.learnware_list: From c46ab025fd880b61cffd10cb589d1fcccdca46af Mon Sep 17 00:00:00 2001 From: chenzx Date: Fri, 7 Apr 2023 11:02:23 +0800 Subject: [PATCH 3/4] [MNT] Update example, modify pipeline, add database function --- examples/example_market_db/example_db.py | 4 +++- learnware/market/database_ops.py | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/example_market_db/example_db.py b/examples/example_market_db/example_db.py index a03feb7..cc9e544 100644 --- a/examples/example_market_db/example_db.py +++ b/examples/example_market_db/example_db.py @@ -16,7 +16,8 @@ def prepare_learnware(learnware_num=10): os.makedirs(dir_path, exist_ok=True) print("Preparing Learnware: %d" % (i)) - data_X = np.random.randn(5000, 20) + data_X = np.random.randn(5000, 20) * i + # print(data_X[:10]) data_y = np.random.randn(5000) data_y = np.where(data_y > 0, 1, 0) @@ -32,6 +33,7 @@ def prepare_learnware(learnware_num=10): def test_market(): + database_ops.clear_learnware_table() easy_market = EasyMarket() print("Total Item:", len(easy_market)) test_learnware_num = 10 diff --git a/learnware/market/database_ops.py b/learnware/market/database_ops.py index 56c5298..03009af 100644 --- a/learnware/market/database_ops.py +++ b/learnware/market/database_ops.py @@ -36,6 +36,16 @@ def init_empty_db(func): return wrapper +# Clear Learnware Database +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# !!!!! !!!!! +# !!!!! Do NOT use unless highly necessary !!!!! +# !!!!! !!!!! +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@init_empty_db +def clear_learnware_table(cur): + LOGGER.warning("!!! Drop Learnware Table !!!") + cur.execute("DROP TABLE LEARNWARE") @init_empty_db def add_learnware_to_db(id: str, name: str, model_path: str, stat_spec_path: str, semantic_spec: dict, cur): From 2a2f62b2f98ae79caf42c02ed49ba053b3964ae9 Mon Sep 17 00:00:00 2001 From: chenzx Date: Fri, 7 Apr 2023 15:10:50 +0800 Subject: [PATCH 4/4] [MNT] Update config --- learnware/config.py | 3 +++ learnware/market/easy.py | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/learnware/config.py b/learnware/config.py index 84f99b1..9b6874a 100644 --- a/learnware/config.py +++ b/learnware/config.py @@ -50,6 +50,8 @@ class Config: ROOT_DIRPATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SPEC_DIRPATH = None +LEARNWARE_POOL_PATH = os.path.join(ROOT_DIRPATH, "learnware_pool") +os.makedirs(LEARNWARE_POOL_PATH, exist_ok=True) semantic_config = { "Data": { @@ -102,6 +104,7 @@ _DEFAULT_CONFIG = { "logging_level": logging.INFO, "specification_path": SPEC_DIRPATH, "semantic_specs": semantic_config, + "model_pool_path": LEARNWARE_POOL_PATH, } C = Config(_DEFAULT_CONFIG) diff --git a/learnware/market/easy.py b/learnware/market/easy.py index a752081..e726d71 100644 --- a/learnware/market/easy.py +++ b/learnware/market/easy.py @@ -345,6 +345,12 @@ class EasyMarket(BaseMarket): def get_semantic_spec_list(self) -> dict: return self.semantic_spec_list + def get_learnware_by_ids(self, id:str): + pass + + def get_learnware_path_by_ids(self, id:str) -> str: + pass + def __len__(self): return len(self.learnware_list.keys())