Files
2026-07-13 12:37:18 +08:00

222 lines
5.5 KiB
Python

# -*- coding:utf-8 -*-
# Author: hankcs
# Date: 2019-08-27 01:27
import json
import logging
import os
import random
from typing import List
import numpy as np
from hanlp_common.constant import PAD
def set_gpu(idx=0):
"""Restrict TensorFlow to only use the GPU of idx
Args:
idx: (Default value = 0)
Returns:
"""
gpus = get_visible_gpus()
if gpus:
try:
tf.config.experimental.set_visible_devices(gpus[idx], 'GPU')
logical_devices = tf.config.experimental.list_logical_devices('GPU')
assert len(logical_devices) == 1
except RuntimeError as e:
# Virtual devices must be set before GPUs have been initialized
# print(e)
raise e
def get_visible_gpus():
gpus = tf.config.experimental.list_physical_devices('GPU')
return gpus
def set_gpu_memory_growth(growth=True):
gpus = get_visible_gpus()
if gpus:
try:
# Currently, memory growth needs to be the same across GPUs
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, growth)
except RuntimeError as e:
# Memory growth must be set before GPUs have been initialized
# print(e)
raise e
def nice_gpu():
"""Use GPU nicely."""
set_gpu_memory_growth()
set_gpu()
def shut_up_python_logging():
logging.getLogger('tensorflow').setLevel(logging.ERROR)
import absl.logging
logging.root.removeHandler(absl.logging._absl_handler)
absl.logging._warn_preinit_stderr = False
def set_tf_loglevel(level=logging.ERROR):
if level >= logging.FATAL:
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
os.environ['TF_CPP_MIN_VLOG_LEVEL'] = '3'
if level >= logging.ERROR:
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
os.environ['TF_CPP_MIN_VLOG_LEVEL'] = '2'
if level >= logging.WARNING:
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '1'
os.environ['TF_CPP_MIN_VLOG_LEVEL'] = '1'
else:
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '0'
os.environ['TF_CPP_MIN_VLOG_LEVEL'] = '0'
shut_up_python_logging()
logging.getLogger('tensorflow').setLevel(level)
set_tf_loglevel()
shut_up_python_logging()
import tensorflow as tf
nice_gpu()
def size_of_dataset(dataset: tf.data.Dataset) -> int:
count = 0
for element in dataset.unbatch().batch(1):
count += 1
return count
def summary_of_model(model: tf.keras.Model):
"""https://stackoverflow.com/a/53668338/3730690
Args:
model: tf.keras.Model:
Returns:
"""
if not model.built:
return 'model structure unknown until calling fit() with some data'
line_list = []
model.summary(print_fn=lambda x: line_list.append(x))
summary = "\n".join(line_list)
return summary
def register_custom_cls(custom_cls, name=None):
if not name:
name = custom_cls.__name__
tf.keras.utils.get_custom_objects()[name] = custom_cls
def set_seed_tf(seed=233):
tf.random.set_seed(seed)
np.random.seed(seed)
random.seed(seed)
def nice():
nice_gpu()
set_seed_tf()
def hanlp_register(arg):
"""Registers a class with the Keras serialization framework.
Args:
arg:
Returns:
"""
class_name = arg.__name__
registered_name = 'HanLP' + '>' + class_name
# if tf_inspect.isclass(arg) and not hasattr(arg, 'get_config'):
# raise ValueError(
# 'Cannot register a class that does not have a get_config() method.')
tf.keras.utils.get_custom_objects()[registered_name] = arg
return arg
def tensor_is_eager(tensor: tf.Tensor):
return hasattr(tensor, 'numpy')
def copy_mask(src: tf.Tensor, dst: tf.Tensor):
mask = getattr(src, '_keras_mask', None)
if mask is not None:
dst._keras_mask = mask
return mask
def get_callback_by_class(callbacks: List[tf.keras.callbacks.Callback], cls) -> tf.keras.callbacks.Callback:
for callback in callbacks:
if isinstance(callback, cls):
return callback
def tf_bernoulli(shape, p, dtype=None):
return tf.keras.backend.random_binomial(shape, p, dtype)
def str_tensor_to_str(str_tensor: tf.Tensor) -> str:
return str_tensor.numpy().decode('utf-8')
def str_tensor_2d_to_list(str_tensor: tf.Tensor, pad=PAD) -> List[List[str]]:
l = []
for i in str_tensor:
sent = []
for j in i:
j = str_tensor_to_str(j)
if j == pad:
break
sent.append(j)
l.append(sent)
return l
def str_tensor_to_list(pred):
return [tag.predict('utf-8') for tag in pred]
def format_metrics(metrics: List[tf.keras.metrics.Metric]):
return ' - '.join(f'{m.name}: {m.result():.4f}' for m in metrics)
class NumpyEncoder(json.JSONEncoder):
def default(self, obj):
"""Special json encoder for numpy types
See https://interviewbubble.com/typeerror-object-of-type-float32-is-not-json-serializable/
Args:
obj: Object to be json encoded.
Returns:
Json string.
"""
if isinstance(obj, (np.int_, np.intc, np.intp, np.int8,
np.int16, np.int32, np.int64, np.uint8,
np.uint16, np.uint32, np.uint64)):
return int(obj)
elif isinstance(obj, (np.float_, np.float16, np.float32,
np.float64)):
return float(obj)
elif isinstance(obj, (np.ndarray,)): #### This is the fix
return obj.tolist()
return json.JSONEncoder.default(self, obj)