diff --git a/oceanai/modules/core/core.py b/oceanai/modules/core/core.py index dc46500..35c9fe3 100644 --- a/oceanai/modules/core/core.py +++ b/oceanai/modules/core/core.py @@ -309,6 +309,13 @@ def __post_init__(self): }, }, }, + "avt": { + "fi": { + "b5": { + "sberdisk": "https://download.sberdisk.ru/download/file/477731594?token=JFCVycXxjnYf3Hg&filename=avt_fi_v2.h5", + }, + }, + }, } # Верные предсказания для подсчета точности diff --git a/oceanai/modules/lab/prediction.py b/oceanai/modules/lab/prediction.py index 348418a..ffbff86 100644 --- a/oceanai/modules/lab/prediction.py +++ b/oceanai/modules/lab/prediction.py @@ -46,6 +46,8 @@ import tensorflow as tf # Машинное обучение от Google import keras +from oceanai.modules.lab.utils.gfl import GFL # Модуль внимания + # ###################################################################################################################### # Сообщения @@ -76,6 +78,23 @@ def __post_init__(self): self._formation_av_models_b5: str = self._formation_models_b5 + self._av_modality + self._formation_avt_model_b5: str = ( + self._("Формирование нейросетевой архитектуры модели для получения " " оценок персональных качеств") + + self._av_modality + ) + self._load_avt_model_weights_b5: str = ( + self._("Загрузка весов нейросетевой модели для получения " "оценок персональных качеств") + + self._av_modality + ) + + self._model_avt_not_formation: str = ( + self._oh + + self._( + "нейросетевая архитектура модели для получения " "оценок по мультимодальным данным не " "сформирована" + ) + + self._av_modality + ) + self._load_av_models_weights_b5: str = self._load_models_weights_b5 + self._av_modality self._concat_av_pred_error: str = self._concat_pred_error + self._av_modality @@ -112,6 +131,8 @@ def __post_init__(self): zip(self._b5["en"], [None] * len(self._b5["en"])) ) + self._avt_model_b5: Optional[keras.engine.functional.Functional] = None + # ----------------------- Только для внутреннего использования внутри класса self.__len_paths: int = 0 # Количество искомых файлов @@ -201,6 +222,16 @@ def av_models_b5_(self) -> Dict[str, Optional[keras.engine.functional.Functional return self._av_models_b5 + @property + def avt_model_b5_(self) -> Optional[keras.engine.functional.Functional]: + """Получение нейросетевой модели **tf.keras.Model** для получения оценок персональных качеств + + Returns: + Dict: Нейроаетевая модель **tf.keras.Model** + """ + + return self._avt_model_b5 + # ------------------------------------------------------------------------------------------------------------------ # Внутренние методы (приватные) # ------------------------------------------------------------------------------------------------------------------ @@ -436,6 +467,165 @@ def __concat_pred_av( return concat + def __load_model_weights( + self, + url: str, + force_reload: bool = True, + info_text: str = "", + out: bool = True, + runtime: bool = True, + run: bool = True, + ) -> bool: + """Загрузка весов нейросетевой модели + + .. note:: + private (приватный метод) + + Args: + url (str): Полный путь к файлу с весами нейросетевой модели + force_reload (bool): Принудительная загрузка файла с весами нейросетевой модели из сети + info_text (str): Текст для информационного сообщения + out (bool): Отображение + runtime (bool): Подсчет времени выполнения + run (bool): Блокировка выполнения + + Returns: + bool: **True** если веса нейросетевой модели загружены, в обратном случае **False** + """ + + self._clear_notebook_history_output() # Очистка истории вывода сообщений в ячейке Jupyter + + try: + # Проверка аргументов + if ( + type(url) is not str + or not url + or type(force_reload) is not bool + or type(info_text) is not str + or not info_text + or type(out) is not bool + or type(runtime) is not bool + or type(run) is not bool + ): + raise TypeError + except TypeError: + self._inv_args(__class__.__name__, self.__load_model_weights.__name__, out=out) + return False + else: + # Блокировка выполнения + if run is False: + self._error(self._lock_user, out=out) + return False + + if runtime: + self._r_start() + + # Информационное сообщение + self._info(info_text, last=False, out=out) + + sections = urlparse(url) # Парсинг URL адреса + + try: + # URL файл невалидный + if sections.scheme == "": + raise requests.exceptions.InvalidURL + except requests.exceptions.InvalidURL: + url = os.path.normpath(url) + + try: + if os.path.isfile(url) is False: + raise FileNotFoundError # Не файл + except FileNotFoundError: + self._other_error(self._load_model_weights_error, out=out) + return False + except Exception: + self._other_error(self._unknown_err, out=out) + return False + else: + self._url_last_filename = url + return True + else: + try: + if force_reload is False: + clear_output(True) + # Загрузка файла из URL + res_download_file_from_url = self._download_file_from_url( + url=url, force_reload=force_reload, runtime=False, out=out, run=True + ) + except Exception: + self._other_error(self._unknown_err, out=out) + return False + else: + # Файл загружен + if res_download_file_from_url != 200: + return False + + return True + finally: + if runtime: + self._r_end(out=out) + + def __load_avt_model_b5( + self, show_summary: bool = False, out: bool = True + ) -> Optional[keras.engine.functional.Functional]: + """Формирование нейросетевой архитектуры модели для получения оценок персональных качеств + + .. note:: + private (приватный метод) + + Args: + show_summary (bool): Отображение сформированной нейросетевой архитектуры модели + out (bool): Отображение + + Returns: + Optional[keras.engine.functional.Functional]: + **None** если неверные типы или значения аргументов, в обратном случае нейросетевая модель + **tf.keras.Model** для получения оценок персональных качеств + """ + + try: + # Проверка аргументов + if type(show_summary) is not bool or type(out) is not bool: + raise TypeError + except TypeError: + self._inv_args(__class__.__name__, self.__load_av_model_b5.__name__, out=out) + return None + else: + i_hc_t_1 = tf.keras.Input(shape=(128,), name="hc_t") + i_nn_t_1 = tf.keras.Input(shape=(128,), name="nn_t") + i_hc_a_1 = tf.keras.Input(shape=(256,), name="hc_a") + i_nn_a_1 = tf.keras.Input(shape=(512,), name="nn_a") + i_hc_v_1 = tf.keras.Input(shape=(256,), name="hc_v") + i_nn_v_1 = tf.keras.Input(shape=(2048,), name="nn_v") + + i_hc_t_1_n = tf.keras.layers.LayerNormalization(axis=1, name="ln_hc_t")(i_hc_t_1) + i_nn_t_1_n = tf.keras.layers.LayerNormalization(axis=1, name="ln_nn_t")(i_nn_t_1) + i_hc_a_1_n = tf.keras.layers.LayerNormalization(axis=1, name="ln_hc_a")(i_hc_a_1) + i_nn_a_1_n = tf.keras.layers.LayerNormalization(axis=1, name="ln_nn_a")(i_nn_a_1) + i_hc_v_1_n = tf.keras.layers.LayerNormalization(axis=1, name="ln_hc_v")(i_hc_v_1) + i_nn_v_1_n = tf.keras.layers.LayerNormalization(axis=1, name="ln_nn_v")(i_nn_v_1) + + gf_ta = GFL(output_dim=64, kernel_initializer="truncated_normal", name="gata") + gf_tv = GFL(output_dim=64, kernel_initializer="truncated_normal", name="gatv") + gf_av = GFL(output_dim=64, kernel_initializer="truncated_normal", name="gaav") + + gf_ta_1 = gf_ta([i_hc_t_1_n, i_hc_a_1_n, i_nn_t_1_n, i_nn_a_1_n]) + gf_tv_1 = gf_tv([i_hc_t_1_n, i_hc_v_1_n, i_nn_t_1_n, i_nn_v_1_n]) + gf_av_1 = gf_av([i_hc_a_1_n, i_hc_v_1_n, i_nn_a_1_n, i_nn_v_1_n]) + + concat_1 = tf.keras.backend.concatenate([gf_ta_1, gf_tv_1, gf_av_1]) + + dense = tf.keras.layers.Dense(50, activation="relu", name="dense")(concat_1) + + dense = tf.keras.layers.Dense(5, activation="sigmoid", name="dence_cl")(dense) + + model = tf.keras.Model(inputs=[i_hc_t_1, i_nn_t_1, i_hc_a_1, i_nn_a_1, i_hc_v_1, i_nn_v_1], outputs=dense) + + if show_summary and out: + model.summary() + + return model + def __load_av_model_b5( self, show_summary: bool = False, out: bool = True ) -> Optional[keras.engine.functional.Functional]: @@ -659,6 +849,59 @@ def load_av_models_b5( return True + def load_avt_model_b5( + self, show_summary: bool = False, out: bool = True, runtime: bool = True, run: bool = True + ) -> bool: + """Формирование нейросетевой архитектуры модели для получения оценок персональных качеств + + Args: + show_summary (bool): Отображение последней сформированной нейросетевой архитектуры моделей + out (bool): Отображение + runtime (bool): Подсчет времени выполнения + run (bool): Блокировка выполнения + + Returns: + bool: **True** если нейросетевая архитектура модели сформирована, в обратном случае **False** + """ + + self._clear_notebook_history_output() # Очистка истории вывода сообщений в ячейке Jupyter + + try: + # Проверка аргументов + if ( + type(show_summary) is not bool + or type(out) is not bool + or type(runtime) is not bool + or type(run) is not bool + ): + raise TypeError + except TypeError: + self._inv_args(__class__.__name__, self.load_avt_model_b5.__name__, out=out) + return False + else: + # Блокировка выполнения + if run is False: + self._error(self._lock_user, out=out) + return False + + if runtime: + self._r_start() + + # Информационное сообщение + self._info(self._formation_avt_model_b5, last=False, out=False) + if out: + self.show_notebook_history_output() # Отображение истории вывода сообщений в ячейке Jupyter + + self._avt_model_b5 = self.__load_avt_model_b5() + + if show_summary and out: + self._avt_model_b5.summary() + + if runtime: + self._r_end(out=out) + + return True + def load_av_models_weights_b5( self, url_openness: str, @@ -1435,3 +1678,581 @@ def get_av_union_predictions( finally: if runtime: self._r_end(out=out) + + def load_avt_model_weights_b5( + self, + url: str, + force_reload: bool = True, + out: bool = True, + runtime: bool = True, + run: bool = True, + ) -> bool: + """Загрузка весов нейросетевой модели для получения оценок персональных качеств + + Args: + url (str): Полный путь к файлу с весами нейросетевой модели + force_reload (bool): Принудительная загрузка файлов с весами нейросетевых моделей из сети + out (bool): Отображение + runtime (bool): Подсчет времени выполнения + run (bool): Блокировка выполнения + + Returns: + bool: **True** если веса нейросетевой модели загружены, в обратном случае **False** + """ + + if runtime: + self._r_start() + + if self.__load_model_weights(url, force_reload, self._load_avt_model_weights_b5, out, False, run) is True: + try: + self._avt_model_b5.load_weights(self._url_last_filename) + except Exception: + self._error(self._model_avt_not_formation, out=out) + return False + else: + return True + finally: + if runtime: + self._r_end(out=out) + + return False + + def get_avt_predictions( + self, + depth: int = 1, + recursive: bool = False, + sr: int = 44100, + window_audio: Union[int, float] = 2.0, + step_audio: Union[int, float] = 1.0, + reduction_fps: int = 5, + window_video: int = 10, + step_video: int = 5, + asr: bool = False, + lang: str = "ru", + accuracy=True, + url_accuracy: str = "", + logs: bool = True, + out: bool = True, + runtime: bool = True, + run: bool = True, + ) -> bool: + """Получения прогнозов по аудио, видео и тексту (мультимодальное объединение) + + Args: + depth (int): Глубина иерархии для получения данных + recursive (bool): Рекурсивный поиск данных + sr (int): Частота дискретизации + window_audio (Union[int, float]): Размер окна сегмента аудио сигнала (в секундах) + step_audio (Union[int, float]): Шаг сдвига окна сегмента аудио сигнала (в секундах) + reduction_fps (int): Понижение кадровой частоты + window_video (int): Размер окна сегмента видео сигнала (в кадрах) + step_video (int): Шаг сдвига окна сегмента видео сигнала (в кадрах) + asr (bool): Автоматическое распознавание речи + lang (str): Язык + accuracy (bool): Вычисление точности + url_accuracy (str): Полный путь к файлу с верными предсказаниями для подсчета точности + logs (bool): При необходимости формировать LOG файл + out (bool): Отображение + runtime (bool): Подсчет времени выполнения + run (bool): Блокировка выполнения + + Returns: + bool: **True** если веса прогнозы успешно получены, в обратном случае **False** + """ + + self._clear_notebook_history_output() # Очистка истории вывода сообщений в ячейке Jupyter + + # Сброс + self._df_files = pd.DataFrame() # Пустой DataFrame с данными + self._df_accuracy = pd.DataFrame() # Пустой DataFrame с результатами вычисления точности + + try: + # Проверка аргументов + if ( + type(depth) is not int + or depth < 1 + or type(recursive) is not bool + or type(sr) is not int + or sr < 1 + or ( + (type(window_audio) is not int or window_audio < 1) + and (type(window_audio) is not float or window_audio <= 0) + ) + or ( + (type(step_audio) is not int or step_audio < 1) + and (type(step_audio) is not float or step_audio <= 0) + ) + or type(reduction_fps) is not int + or reduction_fps < 1 + or type(window_video) is not int + or window_video < 1 + or type(step_video) is not int + or step_video < 1 + or type(asr) is not bool + or not isinstance(lang, str) + or lang not in self.lang_traslate + or type(accuracy) is not bool + or type(url_accuracy) is not str + or type(logs) is not bool + or type(out) is not bool + or type(runtime) is not bool + or type(run) is not bool + ): + raise TypeError + except TypeError: + self._inv_args(__class__.__name__, self.get_avt_predictions.__name__, out=out) + return False + else: + # Блокировка выполнения + if run is False: + self._error(self._lock_user, out=out) + return False + + if runtime: + self._r_start() + + try: + # Получение директорий, где хранятся данные + path_to_data = self._get_paths(self.path_to_dataset_, depth, out=out) + if type(path_to_data) is bool: + return False + + if type(self.keys_dataset_) is not list: + raise TypeError + + # Словарь для DataFrame набора данных с данными + self._dict_of_files = dict(zip(self.keys_dataset_, [[] for _ in range(0, len(self.keys_dataset_))])) + # Словарь для DataFrame набора данных с результатами вычисления точности + self._dict_of_accuracy = dict( + zip(self.keys_dataset_[1:], [[] for _ in range(0, len(self.keys_dataset_[1:]))]) + ) + except (TypeError, FileNotFoundError): + self._other_error(self._folder_not_found.format(self._info_wrapper(self.path_to_dataset_)), out=out) + return False + except Exception: + self._other_error(self._unknown_err, out=out) + return False + else: + # Вычисление точности + if accuracy is True: + get_avt_predictions_info = self._get_union_predictions_info + self._get_accuracy_info + else: + get_avt_predictions_info = self._get_union_predictions_info + + get_avt_predictions_info += self._av_modality + + # Вычисление точности + if accuracy is True: + # Информационное сообщение + self._info(get_avt_predictions_info, out=out) + + if not url_accuracy: + url_accuracy = self._true_traits["sberdisk"] + + try: + # Загрузка верных предсказаний + data_true_traits = pd.read_csv(url_accuracy) + except (FileNotFoundError, URLError, UnicodeDecodeError): + self._other_error(self._load_data_true_traits_error, out=out) + return False + except Exception: + self._other_error(self._unknown_err, out=out) + return False + else: + true_traits = [] + self._del_last_el_notebook_history_output() + + paths = [] # Пути до искомых файлов + + # Проход по всем директориям + for curr_path in path_to_data: + empty = True # По умолчанию директория пустая + + # Рекурсивный поиск данных + if recursive is True: + g = Path(curr_path).rglob("*") + else: + g = Path(curr_path).glob("*") + + # Формирование словаря для DataFrame + for p in g: + try: + if type(self.ext_) is not list or len(self.ext_) < 1: + raise TypeError + + self.ext_ = [x.lower() for x in self.ext_] + except TypeError: + self._other_error(self._wrong_ext, out=out) + return False + except Exception: + self._other_error(self._unknown_err, out=out) + return False + else: + # Расширение файла соответствует расширению искомых файлов + if p.suffix.lower() in self.ext_: + if empty is True: + empty = False # Каталог не пустой + + paths.append(p.resolve()) + + try: + self.__len_paths = len(paths) # Количество искомых файлов + + if self.__len_paths == 0: + raise TypeError + except TypeError: + self._other_error(self._files_not_found, out=out) + return False + except Exception: + self._other_error(self._unknown_err, out=out) + return False + else: + # Локальный путь + self.__local_path = lambda path: os.path.join( + *Path(path).parts[-abs((len(Path(path).parts) - len(Path(self.path_to_dataset_).parts))) :] + ) + + last = False # Замена последнего сообщения + + # Проход по всем искомым файлов + for i, curr_path in enumerate(paths): + if i != 0: + last = True + + # Индикатор выполнения + self._progressbar_union_predictions( + get_avt_predictions_info, + i, + self.__local_path(curr_path), + self.__len_paths, + True, + last, + out, + ) + + # Извлечение признаков из акустического сигнала + hc_audio_features, melspectrogram_audio_features = self._get_acoustic_features( + path=str(curr_path.resolve()), + sr=sr, + window=window_audio, + step=step_audio, + last=True, + out=False, + runtime=False, + run=run, + ) + + # Извлечение признаков из визуального сигнала + hc_video_features, nn_video_features = self._get_visual_features( + path=str(curr_path.resolve()), + reduction_fps=reduction_fps, + window=window_video, + step=step_video, + last=True, + out=False, + runtime=False, + run=run, + ) + + # Извлечение признаков из текста + hc_text_features, nn_text_features = self.get_text_features( + path=str(curr_path.resolve()), + asr=asr, + lang=lang, + show_text=False, + out=False, + runtime=False, + run=run, + ) + + hc_text_features = np.expand_dims(hc_text_features, axis=0) + nn_text_features = np.expand_dims(nn_text_features, axis=0) + + if ( + type(hc_audio_features) is list + and type(melspectrogram_audio_features) is list + and type(hc_video_features) is np.ndarray + and type(nn_video_features) is np.ndarray + and type(hc_text_features) is np.ndarray + and type(nn_text_features) is np.ndarray + and len(hc_audio_features) > 0 + and len(melspectrogram_audio_features) > 0 + and len(hc_video_features) > 0 + and len(nn_video_features) > 0 + and len(hc_text_features) > 0 + and len(nn_text_features) > 0 + ): + feature_lambda = lambda feature: np.concatenate( + (np.mean(feature, axis=0), np.std(feature, axis=0)) + ) + + # Коды ошибок нейросетевых моделей (аудио модальность) + code_error_pred_hc_audio = -1 + code_error_pred_melspectrogram_audio = -1 + + try: + # Оправка экспертных признаков в нейросетевую модель + _, features_hc_audio = self.audio_model_hc_( + np.array(hc_audio_features, dtype=np.float16) + ) + except TypeError: + code_error_pred_hc_audio = 1 + except Exception: + code_error_pred_melspectrogram_audio = 2 + + try: + # Отправка нейросетевых признаков в нейросетевую модель + _, features_nn_audio = self.audio_model_nn_( + np.array(melspectrogram_audio_features, dtype=np.float16) + ) + except TypeError: + code_error_pred_melspectrogram_audio = 1 + except Exception: + code_error_pred_melspectrogram_audio = 2 + + if code_error_pred_hc_audio != -1 and code_error_pred_melspectrogram_audio != -1: + self._error(self._models_audio_not_formation, out=out) + return False + + if code_error_pred_hc_audio != -1: + self._error(self._model_audio_hc_not_formation, out=out) + return False + + if code_error_pred_melspectrogram_audio != -1: + self._error(self._model_audio_nn_not_formation, out=out) + return False + + features_hc_audio = np.expand_dims(feature_lambda(features_hc_audio.numpy()), axis=0) + features_nn_audio = np.expand_dims(feature_lambda(features_nn_audio.numpy()), axis=0) + + # Коды ошибок нейросетевых моделей (видео модальность) + code_error_pred_hc_video = -1 + code_error_pred_nn_video = -1 + + try: + # Оправка экспертных признаков в нейросетевую модель + _, features_hc_video = self.video_model_hc_( + np.array(hc_video_features, dtype=np.float16) + ) + except TypeError: + code_error_pred_hc_video = 1 + except Exception: + code_error_pred_hc_video = 2 + + try: + # Отправка нейросетевых признаков в нейросетевую модель + _, features_nn_video = self.video_model_nn_( + np.array(nn_video_features, dtype=np.float16) + ) + except TypeError: + code_error_pred_nn_video = 1 + except Exception: + code_error_pred_nn_video = 2 + + if code_error_pred_hc_video != -1 and code_error_pred_nn_video != -1: + self._error(self._models_video_not_formation, out=out) + return False + + if code_error_pred_hc_video != -1: + self._error(self._model_video_hc_not_formation, out=out) + return False + + if code_error_pred_nn_video != -1: + self._error(self._model_video_nn_not_formation, out=out) + return False + + features_hc_video = np.expand_dims(feature_lambda(features_hc_video.numpy()), axis=0) + features_nn_video = np.expand_dims(feature_lambda(features_nn_video.numpy()), axis=0) + + # Коды ошибок нейросетевых моделей (текст) + code_error_pred_hc_text = -1 + code_error_pred_nn_text = -1 + + try: + # Оправка экспертных признаков в нейросетевую модель + _, features_hc_text = self.text_model_hc_(np.array(hc_text_features, dtype=np.float16)) + except TypeError: + code_error_pred_hc_text = 1 + except Exception: + code_error_pred_hc_text = 2 + + try: + # Отправка нейросетевых признаков в нейросетевую модель + _, features_nn_text = self.text_model_nn_(np.array(nn_text_features, dtype=np.float16)) + except TypeError: + code_error_pred_nn_text = 1 + except Exception: + code_error_pred_nn_text = 2 + + if code_error_pred_hc_text != -1 and code_error_pred_nn_text != -1: + self._error(self._models_text_not_formation, out=out) + return False + + if code_error_pred_hc_text != -1: + self._error(self._model_text_hc_not_formation, out=out) + return False + + if code_error_pred_nn_text != -1: + self._error(self._model_text_nn_not_formation, out=out) + return False + + try: + final_pred = ( + self.avt_model_b5_( + [ + features_hc_text, + features_nn_text, + features_hc_audio, + features_nn_audio, + features_hc_video, + features_nn_video, + ] + ) + .numpy()[0] + .tolist() + ) + except Exception: + self._other_error(self._unknown_err, out=out) + return False + + # Добавление данных в словарь для DataFrame + if self._append_to_list_of_files(str(curr_path.resolve()), final_pred, out) is False: + return False + + # Вычисление точности + if accuracy is True: + try: + true_trait = ( + data_true_traits[data_true_traits.NAME_VIDEO == curr_path.name][ + list(self._b5["en"]) + ] + .values[0] + .tolist() + ) + except IndexError: + self._other_error(self._expert_values_not_found, out=out) + return False + except Exception: + self._other_error(self._unknown_err, out=out) + return False + else: + true_traits.append(true_trait) + else: + # Добавление данных в словарь для DataFrame + if ( + self._append_to_list_of_files( + str(curr_path.resolve()), [None] * len(self._b5["en"]), out + ) + is False + ): + return False + + self._del_last_el_notebook_history_output() + + # Индикатор выполнения + self._progressbar_union_predictions( + get_avt_predictions_info, + self.__len_paths, + self.__local_path(paths[-1]), + self.__len_paths, + True, + last, + out, + ) + + # Отображение в DataFrame с данными + self._df_files = pd.DataFrame.from_dict(data=self._dict_of_files, orient="index").transpose() + self._df_files.index.name = self._keys_id + self._df_files.index += 1 + + self._df_files.index = self._df_files.index.map(str) + + # Отображение + if out is True: + self._add_notebook_history_output(self._df_files.iloc[0 : self.num_to_df_display_, :]) + + # Подсчет точности + if accuracy is True: + mae_curr = [] + + for cnt, name_b5 in enumerate(self._df_files.keys().tolist()[1:]): + try: + mae_curr.append( + mean_absolute_error( + np.asarray(true_traits)[:, cnt], self._df_files[name_b5].to_list() + ) + ) + except IndexError: + continue + except Exception: + continue + + mae_curr = [round(float(i), 4) for i in mae_curr] + mae_mean = round(float(np.mean(mae_curr)), 4) + accuracy_curr = [round(float(i), 4) for i in 1 - np.asarray(mae_curr)] + accuracy_mean = round(float(np.mean(accuracy_curr)), 4) + + for curr_acc in [mae_curr, accuracy_curr]: + # Добавление данных в словарь для DataFrame с результатами вычисления точности + if self._append_to_list_of_accuracy(curr_acc, out) is False: + return False + + self._dict_of_accuracy.update({self.__df_accuracy_mean: [mae_mean, accuracy_mean]}) + # Отображение в DataFrame с данными + self._df_accuracy = pd.DataFrame.from_dict( + data=self._dict_of_accuracy, orient="index" + ).transpose() + self._df_accuracy.index = self.__df_accuracy_index + self._df_accuracy.index.name = self.__df_accuracy_index_name + + # Информационное сообщение + self._info(self._get_union_predictions_result, out=False) + + # Отображение + if out is True: + self._add_notebook_history_output(self._df_accuracy.iloc[0 : self.num_to_df_display_, :]) + + self._info( + self._get_union_predictions_results_mean.format( + self._info_wrapper(str(mae_mean)), self._info_wrapper(str(accuracy_mean)) + ), + out=False, + ) + + clear_output(True) + # Отображение истории вывода сообщений в ячейке Jupyter + if out is True: + self.show_notebook_history_output() + + if logs is True: + # Текущее время для лог-файла + # см. datetime.fromtimestamp() + curr_ts = str(datetime.now().timestamp()).replace(".", "_") + + name_logs_file = self.get_avt_predictions.__name__ + + # Сохранение LOG + res_save_logs_df_files = self._save_logs( + self._df_files, name_logs_file + "_df_files_" + curr_ts + ) + + # Подсчет точности + if accuracy is True: + # Сохранение LOG + res_save_logs_df_accuracy = self._save_logs( + self._df_accuracy, name_logs_file + "_df_accuracy_" + curr_ts + ) + + if res_save_logs_df_files is True: + # Сохранение LOG файла/файлов + if accuracy is True and res_save_logs_df_accuracy is True: + logs_s = self._logs_saves_true + else: + logs_s = self._logs_save_true + + self._info_true(logs_s, out=out) + + return True + finally: + if runtime: + self._r_end(out=out) diff --git a/oceanai/modules/lab/text.py b/oceanai/modules/lab/text.py index a200c7f..28c8d49 100644 --- a/oceanai/modules/lab/text.py +++ b/oceanai/modules/lab/text.py @@ -198,6 +198,7 @@ def __post_init__(self): self.__multi_corpora: List[str] = ["fi", "mupta"] self.__lang_traslate: List[str] = ["ru", "en"] + self.lang_traslate: List[str] = self.__lang_traslate self.__parse_text_features: Optional[FunctionType] = None # Парсинг экспертных признаков self.__category_text_features: List[str] = [] # Словарь с экспертными признаками diff --git a/oceanai/modules/lab/utils/gfl.py b/oceanai/modules/lab/utils/gfl.py new file mode 100644 index 0000000..4e79917 --- /dev/null +++ b/oceanai/modules/lab/utils/gfl.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Модуль внимания +""" + +import tensorflow as tf # Машинное обучение от Google + +from tensorflow.keras import backend as K +from tensorflow.keras import initializers +from tensorflow.keras import regularizers + + +class GFL(tf.keras.layers.Layer): + def __init__(self, output_dim, kernel_initializer="glorot_uniform", kernel_regularizer=None, **kwargs): + self.output_dim = output_dim + self.kernel_initializer = initializers.get(kernel_initializer) + self.kernel_regularizer = regularizers.get(kernel_regularizer) + super(GFL, self).__init__(**kwargs) + + def build(self, input_shape): + self.W_HCF1 = self.add_weight( + name="W_HCF1", + shape=(int(input_shape[0][1]), self.output_dim), + initializer=self.kernel_initializer, + regularizer=self.kernel_regularizer, + trainable=True, + ) + self.W_DF1 = self.add_weight( + name="W_DF1", + shape=(int(input_shape[2][1]), self.output_dim), + initializer=self.kernel_initializer, + regularizer=self.kernel_regularizer, + trainable=True, + ) + self.W_HCF2 = self.add_weight( + name="W_HCF2", + shape=(int(input_shape[1][1]), self.output_dim), + initializer=self.kernel_initializer, + regularizer=self.kernel_regularizer, + trainable=True, + ) + self.W_DF2 = self.add_weight( + name="W_DF2", + shape=(int(input_shape[3][1]), self.output_dim), + initializer=self.kernel_initializer, + regularizer=self.kernel_regularizer, + trainable=True, + ) + + dim_size1 = int(input_shape[0][1]) + int(input_shape[1][1]) + dim_size2 = int(input_shape[2][1]) + int(input_shape[3][1]) + + self.W_HCF = self.add_weight( + name="W_HCF", + shape=(dim_size1, self.output_dim), + initializer=self.kernel_initializer, + regularizer=self.kernel_regularizer, + trainable=True, + ) + + self.W_DF = self.add_weight( + name="W_DF", + shape=(dim_size2, self.output_dim), + initializer=self.kernel_initializer, + regularizer=self.kernel_regularizer, + trainable=True, + ) + super(GFL, self).build(input_shape) + + def call(self, inputs): + HCF1, HCF2, DF1, DF2 = inputs + + h_HCF1 = K.tanh(K.dot(HCF1, self.W_HCF1)) + h_HCF2 = K.tanh(K.dot(HCF2, self.W_HCF2)) + h_DF1 = K.tanh(K.dot(DF1, self.W_DF1)) + h_DF2 = K.tanh(K.dot(DF2, self.W_DF2)) + + h_HCF = K.sigmoid(K.dot(K.concatenate([HCF1, HCF2]), self.W_HCF)) + h_DF = K.sigmoid(K.dot(K.concatenate([DF1, DF2]), self.W_DF)) + + h = h_HCF * h_HCF1 + (1 - h_HCF) * h_HCF2 + h_DF * h_DF1 + (1 - h_DF) * h_DF2 + + return h + + def compute_output_shape(self, input_shape): + assert isinstance(input_shape, list) + return (int(input_shape[0][0]), self.output_dim) + + def get_config(self): + config = { + "output_dim": self.output_dim, + "kernel_initializer": initializers.serialize(self.kernel_initializer), + "kernel_regularizer": regularizers.serialize(self.kernel_regularizer), + } + base_config = super(GFL, self).get_config() + return dict(list(base_config.items()) + list(config.items()))