diff options
| author | CoprDistGit <infra@openeuler.org> | 2023-05-10 05:52:17 +0000 |
|---|---|---|
| committer | CoprDistGit <infra@openeuler.org> | 2023-05-10 05:52:17 +0000 |
| commit | aae0176579460347a07dd9e3097a5ac1cf1b4cfd (patch) | |
| tree | 514e7df454d1d7dae025142899d6d997733c809a | |
| parent | 1b899facf67d48987ca095cdb76e168d7dafd148 (diff) | |
automatic import of python-tensorneko
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | python-tensorneko.spec | 1994 | ||||
| -rw-r--r-- | sources | 1 |
3 files changed, 1996 insertions, 0 deletions
@@ -0,0 +1 @@ +/tensorneko-0.2.11.tar.gz diff --git a/python-tensorneko.spec b/python-tensorneko.spec new file mode 100644 index 0000000..8fb3486 --- /dev/null +++ b/python-tensorneko.spec @@ -0,0 +1,1994 @@ +%global _empty_manifest_terminate_build 0 +Name: python-tensorneko +Version: 0.2.11 +Release: 1 +Summary: Tensor Neural Engine Kompanion. An util library based on PyTorch and PyTorch Lightning. +License: MIT License +URL: https://github.com/ControlNet/tensorneko +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/bd/f8/682fc5d86aad7f73f66e3e4077b840153e89a00e6c1c2d3b22376f0a08f8/tensorneko-0.2.11.tar.gz +BuildArch: noarch + +Requires: python3-torch +Requires: python3-torchaudio +Requires: python3-torchvision +Requires: python3-torchmetrics +Requires: python3-pytorch-lightning +Requires: python3-pillow +Requires: python3-av +Requires: python3-numpy +Requires: python3-einops +Requires: python3-tensorneko-util +Requires: python3-pysoundfile + +%description +<h1 style="text-align: center">TensorNeko</h1> + +<div align="center"> + <img src="https://img.shields.io/github/stars/ControlNet/tensorneko?style=flat-square"> + <img src="https://img.shields.io/github/forks/ControlNet/tensorneko?style=flat-square"> + <a href="https://github.com/ControlNet/tensorneko/issues"><img src="https://img.shields.io/github/issues/ControlNet/tensorneko?style=flat-square"></a> + <a href="https://pypi.org/project/tensorneko/"><img src="https://img.shields.io/pypi/v/tensorneko?style=flat-square"></a> + <a href="https://pypi.org/project/tensorneko/"><img src="https://img.shields.io/pypi/dm/tensorneko?style=flat-square"></a> + <img src="https://img.shields.io/github/license/ControlNet/tensorneko?style=flat-square"> +</div> + +<div align="center"> + <a href="https://www.python.org/"><img src="https://img.shields.io/pypi/pyversions/tensorneko?style=flat-square"></a> + <a href="https://pytorch.org/"><img src="https://img.shields.io/badge/PyTorch-%3E%3D1.9.0-EE4C2C?style=flat-square&logo=pytorch"></a> + <a href="https://www.pytorchlightning.ai/"><img src="https://img.shields.io/badge/Pytorch%20Lightning-1.7.*-792EE5?style=flat-square&logo=pytorch-lightning"></a> +</div> + +<div align="center"> + <a href="https://github.com/ControlNet/tensorneko/actions"><img src="https://img.shields.io/github/actions/workflow/status/ControlNet/tensorneko/unittest.yml?branch=dev&label=unittest&style=flat-square"></a> + <a href="https://github.com/ControlNet/tensorneko/actions"><img src="https://img.shields.io/github/actions/workflow/status/ControlNet/tensorneko/release.yml?branch=master&label=release&style=flat-square"></a> + <a href="https://coveralls.io/github/ControlNet/tensorneko"><img src="https://img.shields.io/coverallsCoverage/github/ControlNet/tensorneko?style=flat-square"></a> +</div> + +Tensor Neural Engine Kompanion. An util library based on PyTorch and PyTorch Lightning. + +## Install + +```shell +pip install tensorneko +``` + +To use the library without PyTorch and PyTorch Lightning, you can install the util library (support Python 3.7 ~ 3.10 with limited features) with following command. +```shell +pip install tensorneko_util +``` + +## Neko Layers, Modules and Architectures + +Build an MLP with linear layers. The activation and normalization will be placed in the hidden layers. + +784 -> 1024 -> 512 -> 10 + +```python +import tensorneko as neko +import torch.nn + +mlp = neko.module.MLP( + neurons=[784, 1024, 512, 10], + build_activation=torch.nn.ReLU, + build_normalization=[ + lambda: torch.nn.BatchNorm1d(1024), + lambda: torch.nn.BatchNorm1d(512) + ], + dropout_rate=0.5 +) +``` + +Build a Conv2d with activation and normalization. + +```python +import tensorneko as neko +import torch.nn + +conv2d = neko.layer.Conv2d( + in_channels=256, + out_channels=1024, + kernel_size=(3, 3), + padding=(1, 1), + build_activation=torch.nn.ReLU, + build_normalization=lambda: torch.nn.BatchNorm2d(256), + normalization_after_activation=False +) +``` + +#### All architectures, modules and layers + +Layers: + +- `Aggregation` +- `Concatenate` +- `Conv`, `Conv1d`, `Conv2d`, `Conv3d` +- `GaussianNoise` +- `ImageAttention`, `SeqAttention` +- `MaskedConv2d`, `MaskedConv2dA`, `MaskedConv2dB` +- `Linear` +- `Log` +- `PatchEmbedding2d` +- `PositionalEmbedding` +- `Reshape` +- `Stack` +- `VectorQuantizer` + +Modules: + +- `DenseBlock` +- `InceptionModule` +- `MLP` +- `ResidualBlock` and `ResidualModule` +- `AttentionModule`, `TransformerEncoderBlock` and `TransformerEncoder` +- `GatedConv` + +Architectures: +- `AutoEncoder` +- `GAN` +- `WGAN` +- `VQVAE` + +## Neko modules + +All `tensorneko.layer` and `tensorneko.module` are `NekoModule`. They can be used in +[fn.py](https://github.com/kachayev/fn.py) pipe operation. + +```python +from tensorneko.layer import Linear +from torch.nn import ReLU +import torch + +linear0 = Linear(16, 128, build_activation=ReLU) +linear1 = Linear(128, 1) + +f = linear0 >> linear1 +print(f(torch.rand(16)).shape) +# torch.Size([1]) +``` + +## Neko IO + +Easily load and save different modal data. + +```python +import tensorneko as neko +from tensorneko.io import json_data +from typing import List + +# read video (Temporal, Channel, Height, Width) +video_tensor, audio_tensor, video_info = neko.io.read.video("path/to/video.mp4") +# write video +neko.io.write.video("path/to/video.mp4", + video_tensor, video_info.video_fps, + audio_tensor, video_info.audio_fps +) + +# read audio (Channel, Temporal) +audio_tensor, sample_rate = neko.io.read.audio("path/to/audio.wav") +# write audio +neko.io.write.audio("path/to/audio.wav", audio_tensor, sample_rate) + +# read image (Channel, Height, Width) with float value in range [0, 1] +image_tensor = neko.io.read.image("path/to/image.png") +# write image +neko.io.write.image("path/to/image.png", image_tensor) +neko.io.write.image("path/to/image.jpg", image_tensor) + +# read plain text +text_string = neko.io.read.text("path/to/text.txt") +# write plain text +neko.io.write.text("path/to/text.txt", text_string) + +# read json as python dict or list +json_dict = neko.io.read.json("path/to/json.json") +# read json as an object +@json_data +class JsonData: + x: int + y: int + +json_obj: List[JsonData] = neko.io.read.json("path/to/json.json", cls=List[JsonData]) +# write json from python dict/list or json_data decorated object +neko.io.write.json("path/to/json.json", json_dict) +neko.io.write.json("path/to/json.json", json_obj) +``` + +Besides, the read/write for `mat` and `pickle` files is also supported. + + +## Neko preprocessing + +```python +import tensorneko as neko + +# A video tensor with (120, 3, 720, 1280) +video = neko.io.read.video("example/video.mp4").video +# Get a resized tensor with (120, 3, 256, 256) +resized_video = neko.preprocess.resize_video(video, (256, 256)) +``` + +#### All preprocessing utils + +- `resize_video` +- `resize_image` +- `padding_video` +- `padding_audio` +- `crop_with_padding` +- `frames2video` + +if `ffmpeg` is available, you can use below ffmpeg wrappers. + +- `video2frames` +- `merge_video_audio` +- `resample_video_fps` +- `mp32wav` + +## Neko Visualization + +### Variable Web Watcher +Start a web server to watch the variable status when the program (e.g. training, inference, data preprocessing) is running. +```python +import time +from tensorneko.visualization.watcher import * +data_list = ... # a list of data +def preprocessing(d): ... + +# initialize the components +pb = ProgressBar("Processing", total=len(data_list)) +logger = Logger("Log message") +var = Variable("Some Value", 0) +line_chart = LineChart("Line Chart", x_label="x", y_label="y") +view = View("Data preprocessing").add_all() + +t0 = time.time() +# open server when the code block in running. +with Server(view, port=8000): + for i, data in enumerate(data_list): + preprocessing(data) # do some processing here + + x = time.time() - t0 # time since the start of the program + y = i # processed number of data + line_chart.add(x, y) # add to the line chart + logger.log("Some messages") # log messages to the server + var.value = ... # keep tracking a variable + pb.add(1) # update the progress bar by add 1 +``` +When the script is running, go to `127.0.0.1:8000` to keep tracking the status. + +### Tensorboard Server + +Simply run tensorboard server in Python script. +```python +import tensorneko as neko + +with neko.visualization.tensorboard.Server(port=6006): + trainer.fit(model, dm) +``` + +### Matplotlib wrappers +Display an image of (C, H, W) shape by `plt.imshow` wrapper. +```python +import tensorneko as neko +import matplotlib.pyplot as plt + +image_tensor = ... # an image tensor with shape (C, H, W) +neko.visualization.matplotlib.imshow(image_tensor) +plt.show() +``` + +### Predefined colors +Several aesthetic colors are predefined. + +```python +import tensorneko as neko +import matplotlib.pyplot as plt + +# use with matplotlib +plt.plot(..., color=neko.visualization.Colors.RED) + +# the palette for seaborn is also available +from tensorneko_util.visualization.seaborn import palette +import seaborn as sns +sns.set_palette(palette) +``` + +## Neko Model + +Build and train a simple model for classifying MNIST with MLP. + +```python +from typing import Optional, Union, Sequence, Dict, List + +import torch.nn +from torch import Tensor +from torch.optim import Adam +from torchmetrics import Accuracy +from pytorch_lightning.callbacks import ModelCheckpoint + +import tensorneko as neko +from tensorneko.util import get_activation, get_loss + + +class MnistClassifier(neko.NekoModel): + + def __init__(self, name: str, mlp_neurons: List[int], activation: str, dropout_rate: float, loss: str, + learning_rate: float, weight_decay: float + ): + super().__init__(name) + self.weight_decay = weight_decay + self.learning_rate = learning_rate + + self.flatten = torch.nn.Flatten() + self.mlp = neko.module.MLP( + neurons=mlp_neurons, + build_activation=get_activation(activation), + dropout_rate=dropout_rate + ) + self.loss_func = get_loss(loss)() + self.acc_func = Accuracy() + + def forward(self, x): + # (batch, 28, 28) + x = self.flatten(x) + # (batch, 768) + x = self.mlp(x) + # (batch, 10) + return x + + def training_step(self, batch: Optional[Union[Tensor, Sequence[Tensor]]] = None, batch_idx: Optional[int] = None, + optimizer_idx: Optional[int] = None, hiddens: Optional[Tensor] = None + ) -> Dict[str, Tensor]: + x, y = batch + logit = self(x) + prob = logit.sigmoid() + loss = self.loss_func(logit, y) + acc = self.acc_func(prob.max(dim=1)[1], y) + return {"loss": loss, "acc": acc} + + def validation_step(self, batch: Optional[Union[Tensor, Sequence[Tensor]]] = None, batch_idx: Optional[int] = None, + dataloader_idx: Optional[int] = None + ) -> Dict[str, Tensor]: + x, y = batch + logit = self(x) + prob = logit.sigmoid() + loss = self.loss_func(logit, y) + acc = self.acc_func(prob.max(dim=1)[1], y) + return {"loss": loss, "acc": acc} + + def configure_optimizers(self): + optimizer = Adam(self.parameters(), lr=self.learning_rate, betas=(0.5, 0.9), weight_decay=self.weight_decay) + return { + "optimizer": optimizer + } + + +model = MnistClassifier("mnist_mlp_classifier", [784, 1024, 512, 10], "ReLU", 0.5, "CrossEntropyLoss", 1e-4, 1e-4) + +dm = ... # The MNIST datamodule from PyTorch Lightning + +trainer = neko.NekoTrainer(log_every_n_steps=100, gpus=1, logger=model.name, precision=32, + callbacks=[ModelCheckpoint(dirpath="./ckpt", + save_last=True, filename=model.name + "-{epoch}-{val_acc:.3f}", monitor="val_acc", mode="max" + )]) + +trainer.fit(model, dm) +``` + +## Neko Callbacks + +Some simple but useful pytorch-lightning callbacks are provided. + +- `DisplayMetricsCallback` +- `EarlyStoppingLR`: Early stop training when learning rate reaches threshold. + +## Neko Notebook Helpers +Here are some helper functions to better interact with Jupyter Notebook. +```python +import tensorneko as neko +# display a video +neko.notebook.display.video("path/to/video.mp4") +# display an audio +neko.notebook.display.audio("path/to/audio.wav") +# display a code file +neko.notebook.display.code("path/to/code.java") +``` + +## Neko Debug Tools + +Get the default values from `ArgumentParser` args. It's convenient to use this in the notebook. +```python +from argparse import ArgumentParser +from tensorneko.debug import get_parser_default_args + +parser = ArgumentParser() +parser.add_argument("integers", type=int, nargs="+", default=[1, 2, 3]) +parser.add_argument("--sum", dest="accumulate", action="store_const", const=sum, default=max) +args = get_parser_default_args(parser) + +print(args.integers) # [1, 2, 3] +print(args.accumulate) # <function sum at ...> +``` + +## Neko Evaluation + +Some metrics function for evaluation are provided. + +- `iou_1d` +- `iou_2d` +- `psnr_video` +- `psnr_image` +- `ssim_video` +- `ssim_image` + + +## Neko Utilities + +### Misc functions + +`__`: The arguments to pipe operator. (Inspired from [fn.py](https://github.com/kachayev/fn.py)) +```python +from tensorneko.util import __, _ +result = __(20) >> (_ + 1) >> (_ * 2) >> __.get +print(result) +# 42 +``` + +`Seq` and `Stream`: A collection wrapper for method chaining with concurrent supporting. +```python +from tensorneko.util import Seq, Stream, _ +from tensorneko_util.backend.parallel import ParallelType +# using method chaining +seq = Seq.of(1, 2, 3).map(_ + 1).filter(_ % 2 == 0).map(_ * 2).take(2).to_list() +# return [4, 8] + +# using bit shift operator to chain the sequence +seq = Seq.of(1, 2, 3) << Seq.of(2, 3, 4) << [3, 4, 5] +# return Seq(1, 2, 3, 2, 3, 4, 3, 4, 5) + +# run concurrent with `for_each` for Stream +if __name__ == '__main__': + Stream.of(1, 2, 3, 4).for_each(print, progress_bar=True, parallel_type=ParallelType.PROCESS) +``` + +`Option`: A monad for dealing with data. +```python +from tensorneko.util import return_option + +@return_option +def get_data(): + if some_condition: + return 1 + else: + return None + +def process_data(n: int): + if condition(n): + return n + else: + return None + + +data = get_data() +data = data.map(process_data).get_or_else(-1) # if the response is None, return -1 +``` + +`Eval`: A monad for lazy evaluation. +```python +from tensorneko.util import Eval + +@Eval.always +def call_by_name_var(): + return 42 + +@Eval.later +def call_by_need_var(): + return 43 + +@Eval.now +def call_by_value_var(): + return 44 + + +print(call_by_name_var.value) # 42 +``` + +### Reactive +This library provides event bus based reactive tools. The API integrates the Python type annotation syntax. + +```python +# useful decorators for default event bus +from tensorneko.util import ( + subscribe, # run in the main thread + subscribe_thread, # run in a new thread + subscribe_async, # run async + subscribe_process # run in a new process +) +# Event base type +from tensorneko.util import Event + +class LogEvent(Event): + def __init__(self, message: str): + self.message = message + +# the event argument should be annotated correctly +@subscribe +def log_information(event: LogEvent): + print(event.message) + +@subscribe_thread +def log_information_thread(event: LogEvent): + print(event.message, "in another thread") + +if __name__ == '__main__': + # emit an event, and then the event handler will be invoked + # The sequential order is not guaranteed + LogEvent("Hello world!") + # one possible output: + # Hello world! in another thread + # Hello world! +``` + +### Multiple Dispatch + +`dispatch`: Multi-dispatch implementation for Python. + +To my knowledge, 3 popular multi-dispatch libraries still have critical limitations. +[plum](https://github.com/wesselb/plum) doesn't support static methods, +[mutipledispatch](https://github.com/mrocklin/multipledispatch) doesn't support Python type annotation syntax and +[multimethod](https://github.com/coady/multimethod) doesn't support default argument. TensorNeko can do it all. + +```python +from tensorneko.util import dispatch + +class DispatchExample: + + @staticmethod + @dispatch + def go() -> None: + print("Go0") + + @staticmethod + @dispatch + def go(x: int) -> None: + print("Go1") + + @staticmethod + @dispatch + def go(x: float, y: float = 1.0) -> None: + print("Go2") + +@dispatch +def come(x: int) -> str: + return "Come1" + +@dispatch.of(str) +def come(x) -> str: + return "Come2" +``` + +### Miscellaneous + +`StringGetter`: Get PyTorch class from string. +```python +import tensorneko as neko +activation = neko.util.get_activation("leakyRelu")() +``` + +`Seed`: The universal seed for `numpy`, `torch` and Python `random`. +```python +from tensorneko.util import Seed +from torch.utils.data import DataLoader + +# set seed to 42 for all numpy, torch and python random +Seed.set(42) + +# Apply seed to parallel workers of DataLoader +DataLoader( + train_dataset, + batch_size=batch_size, + num_workers=num_workers, + worker_init_fn=Seed.get_loader_worker_init(), + generator=Seed.get_torch_generator() +) +``` + +`Timer`: A timer for measuring the time. +```python +from tensorneko.util import Timer +import time + +# use as a context manager with single time +with Timer(): + time.sleep(1) + +# use as a context manager with multiple segments +with Timer() as t: + time.sleep(1) + t.time("sleep A") + time.sleep(1) + t.time("sleep B") + time.sleep(1) + +# use as a decorator +@Timer() +def f(): + time.sleep(1) + print("f") +``` + +`Singleton`: A decorator to make a class as a singleton. Inspired from Scala/Kotlin. +```python +from tensorneko.util import Singleton + +@Singleton +class MyObject: + def __init__(self): + self.value = 0 + + def add(self, value): + self.value += value + return self.value + + +print(MyObject.value) # 0 +MyObject.add(1) +print(MyObject.value) # 1 +``` + +Besides, many miscellaneous functions are also provided. + + +Functions list (in `tensorneko_util`): +- `generate_inf_seq` +- `compose` +- `listdir` +- `with_printed` +- `ifelse` +- `dict_add` +- `as_list` +- `identity` +- `list_to_dict` +- `get_tensorneko_util_path` + +Functions list (in `tensorneko`): +- `reduce_dict_by` +- `summarize_dict_by` +- `with_printed_shape` +- `is_bad_num` +- `count_parameters` + + + + +%package -n python3-tensorneko +Summary: Tensor Neural Engine Kompanion. An util library based on PyTorch and PyTorch Lightning. +Provides: python-tensorneko +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-tensorneko +<h1 style="text-align: center">TensorNeko</h1> + +<div align="center"> + <img src="https://img.shields.io/github/stars/ControlNet/tensorneko?style=flat-square"> + <img src="https://img.shields.io/github/forks/ControlNet/tensorneko?style=flat-square"> + <a href="https://github.com/ControlNet/tensorneko/issues"><img src="https://img.shields.io/github/issues/ControlNet/tensorneko?style=flat-square"></a> + <a href="https://pypi.org/project/tensorneko/"><img src="https://img.shields.io/pypi/v/tensorneko?style=flat-square"></a> + <a href="https://pypi.org/project/tensorneko/"><img src="https://img.shields.io/pypi/dm/tensorneko?style=flat-square"></a> + <img src="https://img.shields.io/github/license/ControlNet/tensorneko?style=flat-square"> +</div> + +<div align="center"> + <a href="https://www.python.org/"><img src="https://img.shields.io/pypi/pyversions/tensorneko?style=flat-square"></a> + <a href="https://pytorch.org/"><img src="https://img.shields.io/badge/PyTorch-%3E%3D1.9.0-EE4C2C?style=flat-square&logo=pytorch"></a> + <a href="https://www.pytorchlightning.ai/"><img src="https://img.shields.io/badge/Pytorch%20Lightning-1.7.*-792EE5?style=flat-square&logo=pytorch-lightning"></a> +</div> + +<div align="center"> + <a href="https://github.com/ControlNet/tensorneko/actions"><img src="https://img.shields.io/github/actions/workflow/status/ControlNet/tensorneko/unittest.yml?branch=dev&label=unittest&style=flat-square"></a> + <a href="https://github.com/ControlNet/tensorneko/actions"><img src="https://img.shields.io/github/actions/workflow/status/ControlNet/tensorneko/release.yml?branch=master&label=release&style=flat-square"></a> + <a href="https://coveralls.io/github/ControlNet/tensorneko"><img src="https://img.shields.io/coverallsCoverage/github/ControlNet/tensorneko?style=flat-square"></a> +</div> + +Tensor Neural Engine Kompanion. An util library based on PyTorch and PyTorch Lightning. + +## Install + +```shell +pip install tensorneko +``` + +To use the library without PyTorch and PyTorch Lightning, you can install the util library (support Python 3.7 ~ 3.10 with limited features) with following command. +```shell +pip install tensorneko_util +``` + +## Neko Layers, Modules and Architectures + +Build an MLP with linear layers. The activation and normalization will be placed in the hidden layers. + +784 -> 1024 -> 512 -> 10 + +```python +import tensorneko as neko +import torch.nn + +mlp = neko.module.MLP( + neurons=[784, 1024, 512, 10], + build_activation=torch.nn.ReLU, + build_normalization=[ + lambda: torch.nn.BatchNorm1d(1024), + lambda: torch.nn.BatchNorm1d(512) + ], + dropout_rate=0.5 +) +``` + +Build a Conv2d with activation and normalization. + +```python +import tensorneko as neko +import torch.nn + +conv2d = neko.layer.Conv2d( + in_channels=256, + out_channels=1024, + kernel_size=(3, 3), + padding=(1, 1), + build_activation=torch.nn.ReLU, + build_normalization=lambda: torch.nn.BatchNorm2d(256), + normalization_after_activation=False +) +``` + +#### All architectures, modules and layers + +Layers: + +- `Aggregation` +- `Concatenate` +- `Conv`, `Conv1d`, `Conv2d`, `Conv3d` +- `GaussianNoise` +- `ImageAttention`, `SeqAttention` +- `MaskedConv2d`, `MaskedConv2dA`, `MaskedConv2dB` +- `Linear` +- `Log` +- `PatchEmbedding2d` +- `PositionalEmbedding` +- `Reshape` +- `Stack` +- `VectorQuantizer` + +Modules: + +- `DenseBlock` +- `InceptionModule` +- `MLP` +- `ResidualBlock` and `ResidualModule` +- `AttentionModule`, `TransformerEncoderBlock` and `TransformerEncoder` +- `GatedConv` + +Architectures: +- `AutoEncoder` +- `GAN` +- `WGAN` +- `VQVAE` + +## Neko modules + +All `tensorneko.layer` and `tensorneko.module` are `NekoModule`. They can be used in +[fn.py](https://github.com/kachayev/fn.py) pipe operation. + +```python +from tensorneko.layer import Linear +from torch.nn import ReLU +import torch + +linear0 = Linear(16, 128, build_activation=ReLU) +linear1 = Linear(128, 1) + +f = linear0 >> linear1 +print(f(torch.rand(16)).shape) +# torch.Size([1]) +``` + +## Neko IO + +Easily load and save different modal data. + +```python +import tensorneko as neko +from tensorneko.io import json_data +from typing import List + +# read video (Temporal, Channel, Height, Width) +video_tensor, audio_tensor, video_info = neko.io.read.video("path/to/video.mp4") +# write video +neko.io.write.video("path/to/video.mp4", + video_tensor, video_info.video_fps, + audio_tensor, video_info.audio_fps +) + +# read audio (Channel, Temporal) +audio_tensor, sample_rate = neko.io.read.audio("path/to/audio.wav") +# write audio +neko.io.write.audio("path/to/audio.wav", audio_tensor, sample_rate) + +# read image (Channel, Height, Width) with float value in range [0, 1] +image_tensor = neko.io.read.image("path/to/image.png") +# write image +neko.io.write.image("path/to/image.png", image_tensor) +neko.io.write.image("path/to/image.jpg", image_tensor) + +# read plain text +text_string = neko.io.read.text("path/to/text.txt") +# write plain text +neko.io.write.text("path/to/text.txt", text_string) + +# read json as python dict or list +json_dict = neko.io.read.json("path/to/json.json") +# read json as an object +@json_data +class JsonData: + x: int + y: int + +json_obj: List[JsonData] = neko.io.read.json("path/to/json.json", cls=List[JsonData]) +# write json from python dict/list or json_data decorated object +neko.io.write.json("path/to/json.json", json_dict) +neko.io.write.json("path/to/json.json", json_obj) +``` + +Besides, the read/write for `mat` and `pickle` files is also supported. + + +## Neko preprocessing + +```python +import tensorneko as neko + +# A video tensor with (120, 3, 720, 1280) +video = neko.io.read.video("example/video.mp4").video +# Get a resized tensor with (120, 3, 256, 256) +resized_video = neko.preprocess.resize_video(video, (256, 256)) +``` + +#### All preprocessing utils + +- `resize_video` +- `resize_image` +- `padding_video` +- `padding_audio` +- `crop_with_padding` +- `frames2video` + +if `ffmpeg` is available, you can use below ffmpeg wrappers. + +- `video2frames` +- `merge_video_audio` +- `resample_video_fps` +- `mp32wav` + +## Neko Visualization + +### Variable Web Watcher +Start a web server to watch the variable status when the program (e.g. training, inference, data preprocessing) is running. +```python +import time +from tensorneko.visualization.watcher import * +data_list = ... # a list of data +def preprocessing(d): ... + +# initialize the components +pb = ProgressBar("Processing", total=len(data_list)) +logger = Logger("Log message") +var = Variable("Some Value", 0) +line_chart = LineChart("Line Chart", x_label="x", y_label="y") +view = View("Data preprocessing").add_all() + +t0 = time.time() +# open server when the code block in running. +with Server(view, port=8000): + for i, data in enumerate(data_list): + preprocessing(data) # do some processing here + + x = time.time() - t0 # time since the start of the program + y = i # processed number of data + line_chart.add(x, y) # add to the line chart + logger.log("Some messages") # log messages to the server + var.value = ... # keep tracking a variable + pb.add(1) # update the progress bar by add 1 +``` +When the script is running, go to `127.0.0.1:8000` to keep tracking the status. + +### Tensorboard Server + +Simply run tensorboard server in Python script. +```python +import tensorneko as neko + +with neko.visualization.tensorboard.Server(port=6006): + trainer.fit(model, dm) +``` + +### Matplotlib wrappers +Display an image of (C, H, W) shape by `plt.imshow` wrapper. +```python +import tensorneko as neko +import matplotlib.pyplot as plt + +image_tensor = ... # an image tensor with shape (C, H, W) +neko.visualization.matplotlib.imshow(image_tensor) +plt.show() +``` + +### Predefined colors +Several aesthetic colors are predefined. + +```python +import tensorneko as neko +import matplotlib.pyplot as plt + +# use with matplotlib +plt.plot(..., color=neko.visualization.Colors.RED) + +# the palette for seaborn is also available +from tensorneko_util.visualization.seaborn import palette +import seaborn as sns +sns.set_palette(palette) +``` + +## Neko Model + +Build and train a simple model for classifying MNIST with MLP. + +```python +from typing import Optional, Union, Sequence, Dict, List + +import torch.nn +from torch import Tensor +from torch.optim import Adam +from torchmetrics import Accuracy +from pytorch_lightning.callbacks import ModelCheckpoint + +import tensorneko as neko +from tensorneko.util import get_activation, get_loss + + +class MnistClassifier(neko.NekoModel): + + def __init__(self, name: str, mlp_neurons: List[int], activation: str, dropout_rate: float, loss: str, + learning_rate: float, weight_decay: float + ): + super().__init__(name) + self.weight_decay = weight_decay + self.learning_rate = learning_rate + + self.flatten = torch.nn.Flatten() + self.mlp = neko.module.MLP( + neurons=mlp_neurons, + build_activation=get_activation(activation), + dropout_rate=dropout_rate + ) + self.loss_func = get_loss(loss)() + self.acc_func = Accuracy() + + def forward(self, x): + # (batch, 28, 28) + x = self.flatten(x) + # (batch, 768) + x = self.mlp(x) + # (batch, 10) + return x + + def training_step(self, batch: Optional[Union[Tensor, Sequence[Tensor]]] = None, batch_idx: Optional[int] = None, + optimizer_idx: Optional[int] = None, hiddens: Optional[Tensor] = None + ) -> Dict[str, Tensor]: + x, y = batch + logit = self(x) + prob = logit.sigmoid() + loss = self.loss_func(logit, y) + acc = self.acc_func(prob.max(dim=1)[1], y) + return {"loss": loss, "acc": acc} + + def validation_step(self, batch: Optional[Union[Tensor, Sequence[Tensor]]] = None, batch_idx: Optional[int] = None, + dataloader_idx: Optional[int] = None + ) -> Dict[str, Tensor]: + x, y = batch + logit = self(x) + prob = logit.sigmoid() + loss = self.loss_func(logit, y) + acc = self.acc_func(prob.max(dim=1)[1], y) + return {"loss": loss, "acc": acc} + + def configure_optimizers(self): + optimizer = Adam(self.parameters(), lr=self.learning_rate, betas=(0.5, 0.9), weight_decay=self.weight_decay) + return { + "optimizer": optimizer + } + + +model = MnistClassifier("mnist_mlp_classifier", [784, 1024, 512, 10], "ReLU", 0.5, "CrossEntropyLoss", 1e-4, 1e-4) + +dm = ... # The MNIST datamodule from PyTorch Lightning + +trainer = neko.NekoTrainer(log_every_n_steps=100, gpus=1, logger=model.name, precision=32, + callbacks=[ModelCheckpoint(dirpath="./ckpt", + save_last=True, filename=model.name + "-{epoch}-{val_acc:.3f}", monitor="val_acc", mode="max" + )]) + +trainer.fit(model, dm) +``` + +## Neko Callbacks + +Some simple but useful pytorch-lightning callbacks are provided. + +- `DisplayMetricsCallback` +- `EarlyStoppingLR`: Early stop training when learning rate reaches threshold. + +## Neko Notebook Helpers +Here are some helper functions to better interact with Jupyter Notebook. +```python +import tensorneko as neko +# display a video +neko.notebook.display.video("path/to/video.mp4") +# display an audio +neko.notebook.display.audio("path/to/audio.wav") +# display a code file +neko.notebook.display.code("path/to/code.java") +``` + +## Neko Debug Tools + +Get the default values from `ArgumentParser` args. It's convenient to use this in the notebook. +```python +from argparse import ArgumentParser +from tensorneko.debug import get_parser_default_args + +parser = ArgumentParser() +parser.add_argument("integers", type=int, nargs="+", default=[1, 2, 3]) +parser.add_argument("--sum", dest="accumulate", action="store_const", const=sum, default=max) +args = get_parser_default_args(parser) + +print(args.integers) # [1, 2, 3] +print(args.accumulate) # <function sum at ...> +``` + +## Neko Evaluation + +Some metrics function for evaluation are provided. + +- `iou_1d` +- `iou_2d` +- `psnr_video` +- `psnr_image` +- `ssim_video` +- `ssim_image` + + +## Neko Utilities + +### Misc functions + +`__`: The arguments to pipe operator. (Inspired from [fn.py](https://github.com/kachayev/fn.py)) +```python +from tensorneko.util import __, _ +result = __(20) >> (_ + 1) >> (_ * 2) >> __.get +print(result) +# 42 +``` + +`Seq` and `Stream`: A collection wrapper for method chaining with concurrent supporting. +```python +from tensorneko.util import Seq, Stream, _ +from tensorneko_util.backend.parallel import ParallelType +# using method chaining +seq = Seq.of(1, 2, 3).map(_ + 1).filter(_ % 2 == 0).map(_ * 2).take(2).to_list() +# return [4, 8] + +# using bit shift operator to chain the sequence +seq = Seq.of(1, 2, 3) << Seq.of(2, 3, 4) << [3, 4, 5] +# return Seq(1, 2, 3, 2, 3, 4, 3, 4, 5) + +# run concurrent with `for_each` for Stream +if __name__ == '__main__': + Stream.of(1, 2, 3, 4).for_each(print, progress_bar=True, parallel_type=ParallelType.PROCESS) +``` + +`Option`: A monad for dealing with data. +```python +from tensorneko.util import return_option + +@return_option +def get_data(): + if some_condition: + return 1 + else: + return None + +def process_data(n: int): + if condition(n): + return n + else: + return None + + +data = get_data() +data = data.map(process_data).get_or_else(-1) # if the response is None, return -1 +``` + +`Eval`: A monad for lazy evaluation. +```python +from tensorneko.util import Eval + +@Eval.always +def call_by_name_var(): + return 42 + +@Eval.later +def call_by_need_var(): + return 43 + +@Eval.now +def call_by_value_var(): + return 44 + + +print(call_by_name_var.value) # 42 +``` + +### Reactive +This library provides event bus based reactive tools. The API integrates the Python type annotation syntax. + +```python +# useful decorators for default event bus +from tensorneko.util import ( + subscribe, # run in the main thread + subscribe_thread, # run in a new thread + subscribe_async, # run async + subscribe_process # run in a new process +) +# Event base type +from tensorneko.util import Event + +class LogEvent(Event): + def __init__(self, message: str): + self.message = message + +# the event argument should be annotated correctly +@subscribe +def log_information(event: LogEvent): + print(event.message) + +@subscribe_thread +def log_information_thread(event: LogEvent): + print(event.message, "in another thread") + +if __name__ == '__main__': + # emit an event, and then the event handler will be invoked + # The sequential order is not guaranteed + LogEvent("Hello world!") + # one possible output: + # Hello world! in another thread + # Hello world! +``` + +### Multiple Dispatch + +`dispatch`: Multi-dispatch implementation for Python. + +To my knowledge, 3 popular multi-dispatch libraries still have critical limitations. +[plum](https://github.com/wesselb/plum) doesn't support static methods, +[mutipledispatch](https://github.com/mrocklin/multipledispatch) doesn't support Python type annotation syntax and +[multimethod](https://github.com/coady/multimethod) doesn't support default argument. TensorNeko can do it all. + +```python +from tensorneko.util import dispatch + +class DispatchExample: + + @staticmethod + @dispatch + def go() -> None: + print("Go0") + + @staticmethod + @dispatch + def go(x: int) -> None: + print("Go1") + + @staticmethod + @dispatch + def go(x: float, y: float = 1.0) -> None: + print("Go2") + +@dispatch +def come(x: int) -> str: + return "Come1" + +@dispatch.of(str) +def come(x) -> str: + return "Come2" +``` + +### Miscellaneous + +`StringGetter`: Get PyTorch class from string. +```python +import tensorneko as neko +activation = neko.util.get_activation("leakyRelu")() +``` + +`Seed`: The universal seed for `numpy`, `torch` and Python `random`. +```python +from tensorneko.util import Seed +from torch.utils.data import DataLoader + +# set seed to 42 for all numpy, torch and python random +Seed.set(42) + +# Apply seed to parallel workers of DataLoader +DataLoader( + train_dataset, + batch_size=batch_size, + num_workers=num_workers, + worker_init_fn=Seed.get_loader_worker_init(), + generator=Seed.get_torch_generator() +) +``` + +`Timer`: A timer for measuring the time. +```python +from tensorneko.util import Timer +import time + +# use as a context manager with single time +with Timer(): + time.sleep(1) + +# use as a context manager with multiple segments +with Timer() as t: + time.sleep(1) + t.time("sleep A") + time.sleep(1) + t.time("sleep B") + time.sleep(1) + +# use as a decorator +@Timer() +def f(): + time.sleep(1) + print("f") +``` + +`Singleton`: A decorator to make a class as a singleton. Inspired from Scala/Kotlin. +```python +from tensorneko.util import Singleton + +@Singleton +class MyObject: + def __init__(self): + self.value = 0 + + def add(self, value): + self.value += value + return self.value + + +print(MyObject.value) # 0 +MyObject.add(1) +print(MyObject.value) # 1 +``` + +Besides, many miscellaneous functions are also provided. + + +Functions list (in `tensorneko_util`): +- `generate_inf_seq` +- `compose` +- `listdir` +- `with_printed` +- `ifelse` +- `dict_add` +- `as_list` +- `identity` +- `list_to_dict` +- `get_tensorneko_util_path` + +Functions list (in `tensorneko`): +- `reduce_dict_by` +- `summarize_dict_by` +- `with_printed_shape` +- `is_bad_num` +- `count_parameters` + + + + +%package help +Summary: Development documents and examples for tensorneko +Provides: python3-tensorneko-doc +%description help +<h1 style="text-align: center">TensorNeko</h1> + +<div align="center"> + <img src="https://img.shields.io/github/stars/ControlNet/tensorneko?style=flat-square"> + <img src="https://img.shields.io/github/forks/ControlNet/tensorneko?style=flat-square"> + <a href="https://github.com/ControlNet/tensorneko/issues"><img src="https://img.shields.io/github/issues/ControlNet/tensorneko?style=flat-square"></a> + <a href="https://pypi.org/project/tensorneko/"><img src="https://img.shields.io/pypi/v/tensorneko?style=flat-square"></a> + <a href="https://pypi.org/project/tensorneko/"><img src="https://img.shields.io/pypi/dm/tensorneko?style=flat-square"></a> + <img src="https://img.shields.io/github/license/ControlNet/tensorneko?style=flat-square"> +</div> + +<div align="center"> + <a href="https://www.python.org/"><img src="https://img.shields.io/pypi/pyversions/tensorneko?style=flat-square"></a> + <a href="https://pytorch.org/"><img src="https://img.shields.io/badge/PyTorch-%3E%3D1.9.0-EE4C2C?style=flat-square&logo=pytorch"></a> + <a href="https://www.pytorchlightning.ai/"><img src="https://img.shields.io/badge/Pytorch%20Lightning-1.7.*-792EE5?style=flat-square&logo=pytorch-lightning"></a> +</div> + +<div align="center"> + <a href="https://github.com/ControlNet/tensorneko/actions"><img src="https://img.shields.io/github/actions/workflow/status/ControlNet/tensorneko/unittest.yml?branch=dev&label=unittest&style=flat-square"></a> + <a href="https://github.com/ControlNet/tensorneko/actions"><img src="https://img.shields.io/github/actions/workflow/status/ControlNet/tensorneko/release.yml?branch=master&label=release&style=flat-square"></a> + <a href="https://coveralls.io/github/ControlNet/tensorneko"><img src="https://img.shields.io/coverallsCoverage/github/ControlNet/tensorneko?style=flat-square"></a> +</div> + +Tensor Neural Engine Kompanion. An util library based on PyTorch and PyTorch Lightning. + +## Install + +```shell +pip install tensorneko +``` + +To use the library without PyTorch and PyTorch Lightning, you can install the util library (support Python 3.7 ~ 3.10 with limited features) with following command. +```shell +pip install tensorneko_util +``` + +## Neko Layers, Modules and Architectures + +Build an MLP with linear layers. The activation and normalization will be placed in the hidden layers. + +784 -> 1024 -> 512 -> 10 + +```python +import tensorneko as neko +import torch.nn + +mlp = neko.module.MLP( + neurons=[784, 1024, 512, 10], + build_activation=torch.nn.ReLU, + build_normalization=[ + lambda: torch.nn.BatchNorm1d(1024), + lambda: torch.nn.BatchNorm1d(512) + ], + dropout_rate=0.5 +) +``` + +Build a Conv2d with activation and normalization. + +```python +import tensorneko as neko +import torch.nn + +conv2d = neko.layer.Conv2d( + in_channels=256, + out_channels=1024, + kernel_size=(3, 3), + padding=(1, 1), + build_activation=torch.nn.ReLU, + build_normalization=lambda: torch.nn.BatchNorm2d(256), + normalization_after_activation=False +) +``` + +#### All architectures, modules and layers + +Layers: + +- `Aggregation` +- `Concatenate` +- `Conv`, `Conv1d`, `Conv2d`, `Conv3d` +- `GaussianNoise` +- `ImageAttention`, `SeqAttention` +- `MaskedConv2d`, `MaskedConv2dA`, `MaskedConv2dB` +- `Linear` +- `Log` +- `PatchEmbedding2d` +- `PositionalEmbedding` +- `Reshape` +- `Stack` +- `VectorQuantizer` + +Modules: + +- `DenseBlock` +- `InceptionModule` +- `MLP` +- `ResidualBlock` and `ResidualModule` +- `AttentionModule`, `TransformerEncoderBlock` and `TransformerEncoder` +- `GatedConv` + +Architectures: +- `AutoEncoder` +- `GAN` +- `WGAN` +- `VQVAE` + +## Neko modules + +All `tensorneko.layer` and `tensorneko.module` are `NekoModule`. They can be used in +[fn.py](https://github.com/kachayev/fn.py) pipe operation. + +```python +from tensorneko.layer import Linear +from torch.nn import ReLU +import torch + +linear0 = Linear(16, 128, build_activation=ReLU) +linear1 = Linear(128, 1) + +f = linear0 >> linear1 +print(f(torch.rand(16)).shape) +# torch.Size([1]) +``` + +## Neko IO + +Easily load and save different modal data. + +```python +import tensorneko as neko +from tensorneko.io import json_data +from typing import List + +# read video (Temporal, Channel, Height, Width) +video_tensor, audio_tensor, video_info = neko.io.read.video("path/to/video.mp4") +# write video +neko.io.write.video("path/to/video.mp4", + video_tensor, video_info.video_fps, + audio_tensor, video_info.audio_fps +) + +# read audio (Channel, Temporal) +audio_tensor, sample_rate = neko.io.read.audio("path/to/audio.wav") +# write audio +neko.io.write.audio("path/to/audio.wav", audio_tensor, sample_rate) + +# read image (Channel, Height, Width) with float value in range [0, 1] +image_tensor = neko.io.read.image("path/to/image.png") +# write image +neko.io.write.image("path/to/image.png", image_tensor) +neko.io.write.image("path/to/image.jpg", image_tensor) + +# read plain text +text_string = neko.io.read.text("path/to/text.txt") +# write plain text +neko.io.write.text("path/to/text.txt", text_string) + +# read json as python dict or list +json_dict = neko.io.read.json("path/to/json.json") +# read json as an object +@json_data +class JsonData: + x: int + y: int + +json_obj: List[JsonData] = neko.io.read.json("path/to/json.json", cls=List[JsonData]) +# write json from python dict/list or json_data decorated object +neko.io.write.json("path/to/json.json", json_dict) +neko.io.write.json("path/to/json.json", json_obj) +``` + +Besides, the read/write for `mat` and `pickle` files is also supported. + + +## Neko preprocessing + +```python +import tensorneko as neko + +# A video tensor with (120, 3, 720, 1280) +video = neko.io.read.video("example/video.mp4").video +# Get a resized tensor with (120, 3, 256, 256) +resized_video = neko.preprocess.resize_video(video, (256, 256)) +``` + +#### All preprocessing utils + +- `resize_video` +- `resize_image` +- `padding_video` +- `padding_audio` +- `crop_with_padding` +- `frames2video` + +if `ffmpeg` is available, you can use below ffmpeg wrappers. + +- `video2frames` +- `merge_video_audio` +- `resample_video_fps` +- `mp32wav` + +## Neko Visualization + +### Variable Web Watcher +Start a web server to watch the variable status when the program (e.g. training, inference, data preprocessing) is running. +```python +import time +from tensorneko.visualization.watcher import * +data_list = ... # a list of data +def preprocessing(d): ... + +# initialize the components +pb = ProgressBar("Processing", total=len(data_list)) +logger = Logger("Log message") +var = Variable("Some Value", 0) +line_chart = LineChart("Line Chart", x_label="x", y_label="y") +view = View("Data preprocessing").add_all() + +t0 = time.time() +# open server when the code block in running. +with Server(view, port=8000): + for i, data in enumerate(data_list): + preprocessing(data) # do some processing here + + x = time.time() - t0 # time since the start of the program + y = i # processed number of data + line_chart.add(x, y) # add to the line chart + logger.log("Some messages") # log messages to the server + var.value = ... # keep tracking a variable + pb.add(1) # update the progress bar by add 1 +``` +When the script is running, go to `127.0.0.1:8000` to keep tracking the status. + +### Tensorboard Server + +Simply run tensorboard server in Python script. +```python +import tensorneko as neko + +with neko.visualization.tensorboard.Server(port=6006): + trainer.fit(model, dm) +``` + +### Matplotlib wrappers +Display an image of (C, H, W) shape by `plt.imshow` wrapper. +```python +import tensorneko as neko +import matplotlib.pyplot as plt + +image_tensor = ... # an image tensor with shape (C, H, W) +neko.visualization.matplotlib.imshow(image_tensor) +plt.show() +``` + +### Predefined colors +Several aesthetic colors are predefined. + +```python +import tensorneko as neko +import matplotlib.pyplot as plt + +# use with matplotlib +plt.plot(..., color=neko.visualization.Colors.RED) + +# the palette for seaborn is also available +from tensorneko_util.visualization.seaborn import palette +import seaborn as sns +sns.set_palette(palette) +``` + +## Neko Model + +Build and train a simple model for classifying MNIST with MLP. + +```python +from typing import Optional, Union, Sequence, Dict, List + +import torch.nn +from torch import Tensor +from torch.optim import Adam +from torchmetrics import Accuracy +from pytorch_lightning.callbacks import ModelCheckpoint + +import tensorneko as neko +from tensorneko.util import get_activation, get_loss + + +class MnistClassifier(neko.NekoModel): + + def __init__(self, name: str, mlp_neurons: List[int], activation: str, dropout_rate: float, loss: str, + learning_rate: float, weight_decay: float + ): + super().__init__(name) + self.weight_decay = weight_decay + self.learning_rate = learning_rate + + self.flatten = torch.nn.Flatten() + self.mlp = neko.module.MLP( + neurons=mlp_neurons, + build_activation=get_activation(activation), + dropout_rate=dropout_rate + ) + self.loss_func = get_loss(loss)() + self.acc_func = Accuracy() + + def forward(self, x): + # (batch, 28, 28) + x = self.flatten(x) + # (batch, 768) + x = self.mlp(x) + # (batch, 10) + return x + + def training_step(self, batch: Optional[Union[Tensor, Sequence[Tensor]]] = None, batch_idx: Optional[int] = None, + optimizer_idx: Optional[int] = None, hiddens: Optional[Tensor] = None + ) -> Dict[str, Tensor]: + x, y = batch + logit = self(x) + prob = logit.sigmoid() + loss = self.loss_func(logit, y) + acc = self.acc_func(prob.max(dim=1)[1], y) + return {"loss": loss, "acc": acc} + + def validation_step(self, batch: Optional[Union[Tensor, Sequence[Tensor]]] = None, batch_idx: Optional[int] = None, + dataloader_idx: Optional[int] = None + ) -> Dict[str, Tensor]: + x, y = batch + logit = self(x) + prob = logit.sigmoid() + loss = self.loss_func(logit, y) + acc = self.acc_func(prob.max(dim=1)[1], y) + return {"loss": loss, "acc": acc} + + def configure_optimizers(self): + optimizer = Adam(self.parameters(), lr=self.learning_rate, betas=(0.5, 0.9), weight_decay=self.weight_decay) + return { + "optimizer": optimizer + } + + +model = MnistClassifier("mnist_mlp_classifier", [784, 1024, 512, 10], "ReLU", 0.5, "CrossEntropyLoss", 1e-4, 1e-4) + +dm = ... # The MNIST datamodule from PyTorch Lightning + +trainer = neko.NekoTrainer(log_every_n_steps=100, gpus=1, logger=model.name, precision=32, + callbacks=[ModelCheckpoint(dirpath="./ckpt", + save_last=True, filename=model.name + "-{epoch}-{val_acc:.3f}", monitor="val_acc", mode="max" + )]) + +trainer.fit(model, dm) +``` + +## Neko Callbacks + +Some simple but useful pytorch-lightning callbacks are provided. + +- `DisplayMetricsCallback` +- `EarlyStoppingLR`: Early stop training when learning rate reaches threshold. + +## Neko Notebook Helpers +Here are some helper functions to better interact with Jupyter Notebook. +```python +import tensorneko as neko +# display a video +neko.notebook.display.video("path/to/video.mp4") +# display an audio +neko.notebook.display.audio("path/to/audio.wav") +# display a code file +neko.notebook.display.code("path/to/code.java") +``` + +## Neko Debug Tools + +Get the default values from `ArgumentParser` args. It's convenient to use this in the notebook. +```python +from argparse import ArgumentParser +from tensorneko.debug import get_parser_default_args + +parser = ArgumentParser() +parser.add_argument("integers", type=int, nargs="+", default=[1, 2, 3]) +parser.add_argument("--sum", dest="accumulate", action="store_const", const=sum, default=max) +args = get_parser_default_args(parser) + +print(args.integers) # [1, 2, 3] +print(args.accumulate) # <function sum at ...> +``` + +## Neko Evaluation + +Some metrics function for evaluation are provided. + +- `iou_1d` +- `iou_2d` +- `psnr_video` +- `psnr_image` +- `ssim_video` +- `ssim_image` + + +## Neko Utilities + +### Misc functions + +`__`: The arguments to pipe operator. (Inspired from [fn.py](https://github.com/kachayev/fn.py)) +```python +from tensorneko.util import __, _ +result = __(20) >> (_ + 1) >> (_ * 2) >> __.get +print(result) +# 42 +``` + +`Seq` and `Stream`: A collection wrapper for method chaining with concurrent supporting. +```python +from tensorneko.util import Seq, Stream, _ +from tensorneko_util.backend.parallel import ParallelType +# using method chaining +seq = Seq.of(1, 2, 3).map(_ + 1).filter(_ % 2 == 0).map(_ * 2).take(2).to_list() +# return [4, 8] + +# using bit shift operator to chain the sequence +seq = Seq.of(1, 2, 3) << Seq.of(2, 3, 4) << [3, 4, 5] +# return Seq(1, 2, 3, 2, 3, 4, 3, 4, 5) + +# run concurrent with `for_each` for Stream +if __name__ == '__main__': + Stream.of(1, 2, 3, 4).for_each(print, progress_bar=True, parallel_type=ParallelType.PROCESS) +``` + +`Option`: A monad for dealing with data. +```python +from tensorneko.util import return_option + +@return_option +def get_data(): + if some_condition: + return 1 + else: + return None + +def process_data(n: int): + if condition(n): + return n + else: + return None + + +data = get_data() +data = data.map(process_data).get_or_else(-1) # if the response is None, return -1 +``` + +`Eval`: A monad for lazy evaluation. +```python +from tensorneko.util import Eval + +@Eval.always +def call_by_name_var(): + return 42 + +@Eval.later +def call_by_need_var(): + return 43 + +@Eval.now +def call_by_value_var(): + return 44 + + +print(call_by_name_var.value) # 42 +``` + +### Reactive +This library provides event bus based reactive tools. The API integrates the Python type annotation syntax. + +```python +# useful decorators for default event bus +from tensorneko.util import ( + subscribe, # run in the main thread + subscribe_thread, # run in a new thread + subscribe_async, # run async + subscribe_process # run in a new process +) +# Event base type +from tensorneko.util import Event + +class LogEvent(Event): + def __init__(self, message: str): + self.message = message + +# the event argument should be annotated correctly +@subscribe +def log_information(event: LogEvent): + print(event.message) + +@subscribe_thread +def log_information_thread(event: LogEvent): + print(event.message, "in another thread") + +if __name__ == '__main__': + # emit an event, and then the event handler will be invoked + # The sequential order is not guaranteed + LogEvent("Hello world!") + # one possible output: + # Hello world! in another thread + # Hello world! +``` + +### Multiple Dispatch + +`dispatch`: Multi-dispatch implementation for Python. + +To my knowledge, 3 popular multi-dispatch libraries still have critical limitations. +[plum](https://github.com/wesselb/plum) doesn't support static methods, +[mutipledispatch](https://github.com/mrocklin/multipledispatch) doesn't support Python type annotation syntax and +[multimethod](https://github.com/coady/multimethod) doesn't support default argument. TensorNeko can do it all. + +```python +from tensorneko.util import dispatch + +class DispatchExample: + + @staticmethod + @dispatch + def go() -> None: + print("Go0") + + @staticmethod + @dispatch + def go(x: int) -> None: + print("Go1") + + @staticmethod + @dispatch + def go(x: float, y: float = 1.0) -> None: + print("Go2") + +@dispatch +def come(x: int) -> str: + return "Come1" + +@dispatch.of(str) +def come(x) -> str: + return "Come2" +``` + +### Miscellaneous + +`StringGetter`: Get PyTorch class from string. +```python +import tensorneko as neko +activation = neko.util.get_activation("leakyRelu")() +``` + +`Seed`: The universal seed for `numpy`, `torch` and Python `random`. +```python +from tensorneko.util import Seed +from torch.utils.data import DataLoader + +# set seed to 42 for all numpy, torch and python random +Seed.set(42) + +# Apply seed to parallel workers of DataLoader +DataLoader( + train_dataset, + batch_size=batch_size, + num_workers=num_workers, + worker_init_fn=Seed.get_loader_worker_init(), + generator=Seed.get_torch_generator() +) +``` + +`Timer`: A timer for measuring the time. +```python +from tensorneko.util import Timer +import time + +# use as a context manager with single time +with Timer(): + time.sleep(1) + +# use as a context manager with multiple segments +with Timer() as t: + time.sleep(1) + t.time("sleep A") + time.sleep(1) + t.time("sleep B") + time.sleep(1) + +# use as a decorator +@Timer() +def f(): + time.sleep(1) + print("f") +``` + +`Singleton`: A decorator to make a class as a singleton. Inspired from Scala/Kotlin. +```python +from tensorneko.util import Singleton + +@Singleton +class MyObject: + def __init__(self): + self.value = 0 + + def add(self, value): + self.value += value + return self.value + + +print(MyObject.value) # 0 +MyObject.add(1) +print(MyObject.value) # 1 +``` + +Besides, many miscellaneous functions are also provided. + + +Functions list (in `tensorneko_util`): +- `generate_inf_seq` +- `compose` +- `listdir` +- `with_printed` +- `ifelse` +- `dict_add` +- `as_list` +- `identity` +- `list_to_dict` +- `get_tensorneko_util_path` + +Functions list (in `tensorneko`): +- `reduce_dict_by` +- `summarize_dict_by` +- `with_printed_shape` +- `is_bad_num` +- `count_parameters` + + + + +%prep +%autosetup -n tensorneko-0.2.11 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-tensorneko -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Wed May 10 2023 Python_Bot <Python_Bot@openeuler.org> - 0.2.11-1 +- Package Spec generated @@ -0,0 +1 @@ +be899609ef9d25c0327c7aa7d5bf5b7e tensorneko-0.2.11.tar.gz |
