From 7613d46d50be0c2aa008267c05ce31faaf4334c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=A6=E6=99=93=E7=8E=B2?= <3174348550@qq.com> Date: Mon, 15 Dec 2025 10:05:42 +0800 Subject: [PATCH] delete redundant files --- docs/sciai/docs/Makefile | 20 - docs/sciai/docs/_ext/myautosummary.py | 521 ------------- .../_ext/overwriteautosummary_generate.txt | 707 ------------------ .../docs/_ext/overwriteobjectiondirective.txt | 374 --------- docs/sciai/docs/_ext/overwriteviewcode.txt | 378 ---------- docs/sciai/docs/requirements.txt | 7 - .../source_en/_templates/classtemplate.rst | 27 - .../docs/source_en/build_model_with_sciai.md | 240 ------ docs/sciai/docs/source_en/conf.py | 272 ------- .../docs/source_en/images/architecture.png | Bin 55443 -> 0 bytes docs/sciai/docs/source_en/index.rst | 52 -- docs/sciai/docs/source_en/installation.md | 74 -- docs/sciai/docs/source_en/launch_with_api.md | 57 -- .../docs/source_en/launch_with_scripts.md | 64 -- docs/sciai/docs/source_en/model_library.md | 74 -- .../source_zh_cn/_templates/classtemplate.rst | 27 - .../source_zh_cn/build_model_with_sciai.md | 240 ------ docs/sciai/docs/source_zh_cn/conf.py | 315 -------- .../source_zh_cn/images/architecture_cn.png | Bin 52511 -> 0 bytes docs/sciai/docs/source_zh_cn/index.rst | 52 -- docs/sciai/docs/source_zh_cn/installation.md | 66 -- .../docs/source_zh_cn/launch_with_api.md | 56 -- .../docs/source_zh_cn/launch_with_scripts.md | 64 -- docs/sciai/docs/source_zh_cn/model_library.md | 72 -- 24 files changed, 3759 deletions(-) delete mode 100644 docs/sciai/docs/Makefile delete mode 100644 docs/sciai/docs/_ext/myautosummary.py delete mode 100644 docs/sciai/docs/_ext/overwriteautosummary_generate.txt delete mode 100644 docs/sciai/docs/_ext/overwriteobjectiondirective.txt delete mode 100644 docs/sciai/docs/_ext/overwriteviewcode.txt delete mode 100644 docs/sciai/docs/requirements.txt delete mode 100644 docs/sciai/docs/source_en/_templates/classtemplate.rst delete mode 100644 docs/sciai/docs/source_en/build_model_with_sciai.md delete mode 100644 docs/sciai/docs/source_en/conf.py delete mode 100644 docs/sciai/docs/source_en/images/architecture.png delete mode 100644 docs/sciai/docs/source_en/index.rst delete mode 100644 docs/sciai/docs/source_en/installation.md delete mode 100644 docs/sciai/docs/source_en/launch_with_api.md delete mode 100644 docs/sciai/docs/source_en/launch_with_scripts.md delete mode 100644 docs/sciai/docs/source_en/model_library.md delete mode 100644 docs/sciai/docs/source_zh_cn/_templates/classtemplate.rst delete mode 100644 docs/sciai/docs/source_zh_cn/build_model_with_sciai.md delete mode 100644 docs/sciai/docs/source_zh_cn/conf.py delete mode 100644 docs/sciai/docs/source_zh_cn/images/architecture_cn.png delete mode 100644 docs/sciai/docs/source_zh_cn/index.rst delete mode 100644 docs/sciai/docs/source_zh_cn/installation.md delete mode 100644 docs/sciai/docs/source_zh_cn/launch_with_api.md delete mode 100644 docs/sciai/docs/source_zh_cn/launch_with_scripts.md delete mode 100644 docs/sciai/docs/source_zh_cn/model_library.md diff --git a/docs/sciai/docs/Makefile b/docs/sciai/docs/Makefile deleted file mode 100644 index 1eff895270..0000000000 --- a/docs/sciai/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source_zh_cn -BUILDDIR = build_zh_cn - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/sciai/docs/_ext/myautosummary.py b/docs/sciai/docs/_ext/myautosummary.py deleted file mode 100644 index 3460bcd2f1..0000000000 --- a/docs/sciai/docs/_ext/myautosummary.py +++ /dev/null @@ -1,521 +0,0 @@ -"""Customized autosummary directives for sphinx.""" - -import importlib -import inspect -import os -import re -from typing import List, Tuple -from docutils.nodes import Node -from sphinx.locale import __ -from sphinx.ext.autosummary import Autosummary, posixpath, addnodes, logger, Matcher, autosummary_toc, get_import_prefixes_from_env -from sphinx.ext.autosummary import mock, StringList, ModuleType, get_documenter, ModuleAnalyzer, PycodeError, mangle_signature -from sphinx.ext.autosummary import import_by_name, extract_summary, autosummary_table, nodes, switch_source_input, rst -from sphinx.ext.autodoc.directive import DocumenterBridge, Options - -class MsAutosummary(Autosummary): - """ - Inherited from sphinx's autosummary, add titles and a column for the generated table. - """ - - def init(self): - """ - init method - """ - self.find_doc_name = "" - self.third_title = "" - self.default_doc = "" - - def extract_env_summary(self, doc: List[str]) -> str: - """Extract env summary from docstring.""" - env_sum = self.default_doc - for i, piece in enumerate(doc): - if piece.startswith(self.find_doc_name): - env_sum = doc[i+1][4:] - return env_sum - - def run(self): - """ - run method - """ - self.init() - self.bridge = DocumenterBridge(self.env, self.state.document.reporter, - Options(), self.lineno, self.state) - - names = [x.strip().split()[0] for x in self.content - if x.strip() and re.search(r'^[~a-zA-Z_]', x.strip()[0])] - items = self.get_items(names) - teble_nodes = self.get_table(items) - - if 'toctree' in self.options: - dirname = posixpath.dirname(self.env.docname) - - tree_prefix = self.options['toctree'].strip() - docnames = [] - excluded = Matcher(self.config.exclude_patterns) - for item in items: - docname = posixpath.join(tree_prefix, item[3]) - docname = posixpath.normpath(posixpath.join(dirname, docname)) - if docname not in self.env.found_docs: - location = self.state_machine.get_source_and_line(self.lineno) - if excluded(self.env.doc2path(docname, None)): - msg = __('autosummary references excluded document %r. Ignored.') - else: - msg = __('autosummary: stub file not found %r. ' - 'Check your autosummary_generate setting.') - logger.warning(msg, item[3], location=location) - continue - docnames.append(docname) - - if docnames: - tocnode = addnodes.toctree() - tocnode['includefiles'] = docnames - tocnode['entries'] = [(None, docn) for docn in docnames] - tocnode['maxdepth'] = -1 - tocnode['glob'] = None - teble_nodes.append(autosummary_toc('', '', tocnode)) - return teble_nodes - - def get_items(self, names: List[str]) -> List[Tuple[str, str, str, str, str]]: - """Try to import the given names, and return a list of - ``[(name, signature, summary_string, real_name, env_summary), ...]``. - """ - prefixes = get_import_prefixes_from_env(self.env) - items = [] # type: List[Tuple[str, str, str, str, str]] - max_item_chars = 50 - - for name in names: - display_name = name - if name.startswith('~'): - name = name[1:] - display_name = name.split('.')[-1] - try: - with mock(self.config.autosummary_mock_imports): - real_name, obj, parent, modname = import_by_name(name, prefixes=prefixes) - except ImportError: - logger.warning(__('failed to import %s'), name) - items.append((name, '', '', name, '')) - continue - - self.bridge.result = StringList() # initialize for each documenter - full_name = real_name - if not isinstance(obj, ModuleType): - # give explicitly separated module name, so that members - # of inner classes can be documented - full_name = modname + '::' + full_name[len(modname) + 1:] - # NB. using full_name here is important, since Documenters - # handle module prefixes slightly differently - doccls = get_documenter(self.env.app, obj, parent) - documenter = doccls(self.bridge, full_name) - - if not documenter.parse_name(): - logger.warning(__('failed to parse name %s'), real_name) - items.append((display_name, '', '', real_name, '')) - continue - if not documenter.import_object(): - logger.warning(__('failed to import object %s'), real_name) - items.append((display_name, '', '', real_name, '')) - continue - if documenter.options.members and not documenter.check_module(): - continue - - # try to also get a source code analyzer for attribute docs - try: - documenter.analyzer = ModuleAnalyzer.for_module( - documenter.get_real_modname()) - # parse right now, to get PycodeErrors on parsing (results will - # be cached anyway) - documenter.analyzer.find_attr_docs() - except PycodeError as err: - logger.debug('[autodoc] module analyzer failed: %s', err) - # no source file -- e.g. for builtin and C modules - documenter.analyzer = None - - # -- Grab the signature - - try: - sig = documenter.format_signature(show_annotation=False) - except TypeError: - # the documenter does not support ``show_annotation`` option - sig = documenter.format_signature() - - if not sig: - sig = '' - else: - max_chars = max(10, max_item_chars - len(display_name)) - sig = mangle_signature(sig, max_chars=max_chars) - - # -- Grab the summary - - documenter.add_content(None) - summary = extract_summary(self.bridge.result.data[:], self.state.document) - env_sum = self.extract_env_summary(self.bridge.result.data[:]) - items.append((display_name, sig, summary, real_name, env_sum)) - - return items - - def get_table(self, items: List[Tuple[str, str, str, str, str]]) -> List[Node]: - """Generate a proper list of table nodes for autosummary:: directive. - - *items* is a list produced by :meth:`get_items`. - """ - table_spec = addnodes.tabular_col_spec() - table_spec['spec'] = r'\X{1}{2}\X{1}{2}' - - table = autosummary_table('') - real_table = nodes.table('', classes=['longtable']) - table.append(real_table) - group = nodes.tgroup('', cols=3) - real_table.append(group) - group.append(nodes.colspec('', colwidth=10)) - group.append(nodes.colspec('', colwidth=70)) - group.append(nodes.colspec('', colwidth=30)) - body = nodes.tbody('') - group.append(body) - - def append_row(*column_texts: str) -> None: - row = nodes.row('', color="red") - source, line = self.state_machine.get_source_and_line() - for text in column_texts: - node = nodes.paragraph('') - vl = StringList() - vl.append(text, '%s:%d:' % (source, line)) - with switch_source_input(self.state, vl): - self.state.nested_parse(vl, 0, node) - try: - if isinstance(node[0], nodes.paragraph): - node = node[0] - except IndexError: - pass - row.append(nodes.entry('', node)) - body.append(row) - - # add table's title - append_row("**API Name**", "**Description**", self.third_title) - for name, sig, summary, real_name, env_sum in items: - qualifier = 'obj' - if 'nosignatures' not in self.options: - col1 = ':%s:`%s <%s>`\\ %s' % (qualifier, name, real_name, rst.escape(sig)) - else: - col1 = ':%s:`%s <%s>`' % (qualifier, name, real_name) - col2 = summary - col3 = env_sum - append_row(col1, col2, col3) - - return [table_spec, table] - - -class MsNoteAutoSummary(MsAutosummary): - """ - Inherited from MsAutosummary. Add a third column about `Note` to the table. - """ - - def init(self): - """ - init method - """ - self.find_doc_name = ".. note::" - self.third_title = "**Note**" - self.default_doc = "None" - - def extract_env_summary(self, doc: List[str]) -> str: - """Extract env summary from docstring.""" - env_sum = self.default_doc - for piece in doc: - if piece.startswith(self.find_doc_name): - env_sum = piece[10:] - return env_sum - - -class MsPlatformAutoSummary(MsAutosummary): - """ - Inherited from MsAutosummary. Add a third column about `Supported Platforms` to the table. - """ - def init(self): - """ - init method - """ - self.find_doc_name = "Supported Platforms:" - self.third_title = "**{}**".format(self.find_doc_name[:-1]) - self.default_doc = "To Be Developed" - -class MsCnAutoSummary(Autosummary): - """Overwrite MsPlatformAutosummary for chinese python api.""" - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.table_head = () - self.find_doc_name = "" - self.third_title = "" - self.default_doc = "" - self.third_name_en = "" - - def get_third_column_en(self, doc): - """Get the third column for en.""" - third_column = self.default_doc - for i, piece in enumerate(doc): - if piece.startswith(self.third_name_en): - try: - if "eprecated" in doc[i+1][4:]: - third_column = "弃用" - else: - third_column = doc[i+1][4:] - except IndexError: - third_column = '' - return third_column - - def get_summary_re(self, display_name: str): - return re.compile(rf'\.\. \w+:\w+::\s+{display_name}.*?\n\n\s+(.*?)[。\n]') - - def run(self) -> List[Node]: - self.bridge = DocumenterBridge(self.env, self.state.document.reporter, - Options(), self.lineno, self.state) - - names = [x.strip().split()[0] for x in self.content - if x.strip() and re.search(r'^[~a-zA-Z_]', x.strip()[0])] - items = self.get_items(names) - #pylint: disable=redefined-outer-name - nodes = self.get_table(items) - - dirname = posixpath.dirname(self.env.docname) - - tree_prefix = self.options['toctree'].strip() - docnames = [] - names = [i[0] for i in items] - for name in names: - docname = posixpath.join(tree_prefix, name) - docname = posixpath.normpath(posixpath.join(dirname, docname)) - if docname not in self.env.found_docs: - continue - - docnames.append(docname) - - if docnames: - tocnode = addnodes.toctree() - tocnode['includefiles'] = docnames - tocnode['entries'] = [(None, docn) for docn in docnames] - tocnode['maxdepth'] = -1 - tocnode['glob'] = None - - nodes.append(autosummary_toc('', '', tocnode)) - - return nodes - - def get_items(self, names: List[str]) -> List[Tuple[str, str, str, str]]: - """Try to import the given names, and return a list of - ``[(name, signature, summary_string, real_name), ...]``. - """ - prefixes = get_import_prefixes_from_env(self.env) - doc_path = os.path.dirname(self.state.document.current_source) - items = [] # type: List[Tuple[str, str, str, str]] - max_item_chars = 50 - origin_rst_files = self.env.config.rst_files - all_rst_files = self.env.found_docs - generated_files = all_rst_files.difference(origin_rst_files) - for name in names: - display_name = name - if name.startswith('~'): - name = name[1:] - display_name = name.split('.')[-1] - - dir_name = self.options['toctree'] - spec_path = os.path.join('api_python', dir_name, display_name) - file_path = os.path.join(doc_path, dir_name, display_name+'.rst') - if os.path.exists(file_path) and spec_path not in generated_files: - summary_re_tag = re.compile(rf'\.\. \w+:\w+::\s+{display_name}.*?\n\s+:.*?:\n\n\s+(.*?)[。\n]') - summary_re_line = re.compile(rf'\.\. \w+:\w+::\s+{display_name}(?:.|\n|)+?\n\n\s+(.*?)[。\n]') - summary_re = self.get_summary_re(display_name) - content = '' - with open(file_path, 'r', encoding='utf-8') as f: - content = f.read() - if content: - summary_str = summary_re.findall(content) - summary_str_tag = summary_re_tag.findall(content) - summary_str_line = summary_re_line.findall(content) - if summary_str: - if re.findall("[::,,。.;;]", summary_str[0][-1]): - logger.warning(f"{display_name}接口的概述格式需调整") - summary_str = summary_str[0] + '。' - elif summary_str_tag: - if re.findall("[::,,。.;;]", summary_str_tag[0][-1]): - logger.warning(f"{display_name}接口的概述格式需调整") - summary_str = summary_str_tag[0] + '。' - elif summary_str_line: - if re.findall("[::,,。.;;]", summary_str_line[0][-1]): - logger.warning(f"{display_name}接口的概述格式需调整") - summary_str = summary_str_line[0] + '。' - else: - summary_str = '' - if not self.table_head: - items.append((display_name, summary_str)) - else: - third_str = self.get_third_column(display_name, content) - if third_str: - third_str = third_str[0] - else: - third_str = '' - - items.append((display_name, summary_str, third_str)) - else: - try: - with mock(self.config.autosummary_mock_imports): - real_name, obj, parent, modname = import_by_name(name, prefixes=prefixes) - except ImportError: - logger.warning(__('failed to import %s'), name) - items.append((name, '', '')) - continue - - self.bridge.result = StringList() # initialize for each documenter - full_name = real_name - if not isinstance(obj, ModuleType): - # give explicitly separated module name, so that members - # of inner classes can be documented - full_name = modname + '::' + full_name[len(modname) + 1:] - # NB. using full_name here is important, since Documenters - # handle module prefixes slightly differently - doccls = get_documenter(self.env.app, obj, parent) - documenter = doccls(self.bridge, full_name) - - if not documenter.parse_name(): - logger.warning(__('failed to parse name %s'), real_name) - items.append((display_name, '', '')) - continue - if not documenter.import_object(): - logger.warning(__('failed to import object %s'), real_name) - items.append((display_name, '', '')) - continue - if documenter.options.members and not documenter.check_module(): - continue - - # try to also get a source code analyzer for attribute docs - try: - documenter.analyzer = ModuleAnalyzer.for_module( - documenter.get_real_modname()) - # parse right now, to get PycodeErrors on parsing (results will - # be cached anyway) - documenter.analyzer.find_attr_docs() - except PycodeError as err: - logger.debug('[autodoc] module analyzer failed: %s', err) - # no source file -- e.g. for builtin and C modules - documenter.analyzer = None - - # -- Grab the signature - - try: - sig = documenter.format_signature(show_annotation=False) - except TypeError: - # the documenter does not support ``show_annotation`` option - sig = documenter.format_signature() - - if not sig: - sig = '' - else: - max_chars = max(10, max_item_chars - len(display_name)) - sig = mangle_signature(sig, max_chars=max_chars) - - # -- Grab the summary and third_colum - - documenter.add_content(None) - summary = extract_summary(self.bridge.result.data[:], self.state.document) - if self.table_head: - third_colum = self.get_third_column_en(self.bridge.result.data[:]) - items.append((display_name, summary, third_colum)) - else: - items.append((display_name, summary)) - - - return items - - def get_table(self, items: List[Tuple[str, str, str]]) -> List[Node]: - """Generate a proper list of table nodes for autosummary:: directive. - - *items* is a list produced by :meth:`get_items`. - """ - table_spec = addnodes.tabular_col_spec() - table = autosummary_table('') - real_table = nodes.table('', classes=['longtable']) - table.append(real_table) - - if not self.table_head: - table_spec['spec'] = r'\X{1}{2}\X{1}{2}' - group = nodes.tgroup('', cols=2) - real_table.append(group) - group.append(nodes.colspec('', colwidth=10)) - group.append(nodes.colspec('', colwidth=90)) - else: - table_spec['spec'] = r'\X{1}{2}\X{1}{2}\X{1}{2}' - group = nodes.tgroup('', cols=3) - real_table.append(group) - group.append(nodes.colspec('', colwidth=10)) - group.append(nodes.colspec('', colwidth=60)) - group.append(nodes.colspec('', colwidth=30)) - body = nodes.tbody('') - group.append(body) - - def append_row(*column_texts: str) -> None: - row = nodes.row('') - source, line = self.state_machine.get_source_and_line() - for text in column_texts: - node = nodes.paragraph('') - vl = StringList() - vl.append(text, '%s:%d:' % (source, line)) - with switch_source_input(self.state, vl): - self.state.nested_parse(vl, 0, node) - try: - if isinstance(node[0], nodes.paragraph): - node = node[0] - except IndexError: - pass - row.append(nodes.entry('', node)) - body.append(row) - append_row(*self.table_head) - if not self.table_head: - for name, summary in items: - qualifier = 'obj' - col1 = ':%s:`%s <%s>`' % (qualifier, name, name) - col2 = summary - append_row(col1, col2) - else: - for name, summary, other in items: - qualifier = 'obj' - col1 = ':%s:`%s <%s>`' % (qualifier, name, name) - col2 = summary - col3 = other - append_row(col1, col2, col3) - return [table_spec, table] - -def get_api(fullname): - """Get the api module.""" - try: - module_name, api_name = ".".join(fullname.split('.')[:-1]), fullname.split('.')[-1] - # pylint: disable=unused-variable - module_import = importlib.import_module(module_name) - except ModuleNotFoundError: - module_name, api_name = ".".join(fullname.split('.')[:-2]), ".".join(fullname.split('.')[-2:]) - module_import = importlib.import_module(module_name) - # pylint: disable=eval-used - api = getattr(module_import, api_name) - return api - -class MsCnPlatformAutoSummary(MsCnAutoSummary): - """definition of cnmsplatformautosummary.""" - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.table_head = ('**接口名**', '**概述**', '**支持平台**') - self.third_name_en = "Supported Platforms:" - - def get_third_column(self, name=None, content=None): - """Get the`Supported Platforms`.""" - if not name: - return [] - try: - api_doc = inspect.getdoc(get_api(name)) - platform_str = re.findall(r'Supported Platforms:\n\s+(.*?)\n\n', api_doc) - if ['deprecated'] == platform_str: - return ["弃用"] - if not platform_str: - platform_str_leak = re.findall(r'Supported Platforms:\n\s+(.*)', api_doc) - if platform_str_leak: - return platform_str_leak - return ["``Ascend`` ``GPU`` ``CPU``"] - return platform_str - except: #pylint: disable=bare-except - return [] diff --git a/docs/sciai/docs/_ext/overwriteautosummary_generate.txt b/docs/sciai/docs/_ext/overwriteautosummary_generate.txt deleted file mode 100644 index 4b0a1b1dd2..0000000000 --- a/docs/sciai/docs/_ext/overwriteautosummary_generate.txt +++ /dev/null @@ -1,707 +0,0 @@ -""" - sphinx.ext.autosummary.generate - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Usable as a library or script to generate automatic RST source files for - items referred to in autosummary:: directives. - - Each generated RST file contains a single auto*:: directive which - extracts the docstring of the referred item. - - Example Makefile rule:: - - generate: - sphinx-autogen -o source/generated source/*.rst - - :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" - -import argparse -import importlib -import inspect -import locale -import os -import pkgutil -import pydoc -import re -import sys -import warnings -from gettext import NullTranslations -from os import path -from typing import Any, Dict, List, NamedTuple, Sequence, Set, Tuple, Type, Union - -from jinja2 import TemplateNotFound -from jinja2.sandbox import SandboxedEnvironment - -import sphinx.locale -from sphinx import __display_version__, package_dir -from sphinx.application import Sphinx -from sphinx.builders import Builder -from sphinx.config import Config -from sphinx.deprecation import RemovedInSphinx50Warning -from sphinx.ext.autodoc import Documenter -from sphinx.ext.autodoc.importer import import_module -from sphinx.ext.autosummary import (ImportExceptionGroup, get_documenter, import_by_name, - import_ivar_by_name) -from sphinx.locale import __ -from sphinx.pycode import ModuleAnalyzer, PycodeError -from sphinx.registry import SphinxComponentRegistry -from sphinx.util import logging, rst, split_full_qualified_name, get_full_modname -from sphinx.util.inspect import getall, safe_getattr -from sphinx.util.osutil import ensuredir -from sphinx.util.template import SphinxTemplateLoader - -logger = logging.getLogger(__name__) - - -class DummyApplication: - """Dummy Application class for sphinx-autogen command.""" - - def __init__(self, translator: NullTranslations) -> None: - self.config = Config() - self.registry = SphinxComponentRegistry() - self.messagelog: List[str] = [] - self.srcdir = "/" - self.translator = translator - self.verbosity = 0 - self._warncount = 0 - self.warningiserror = False - - self.config.add('autosummary_context', {}, True, None) - self.config.add('autosummary_filename_map', {}, True, None) - self.config.add('autosummary_ignore_module_all', True, 'env', bool) - self.config.add('docs_branch', '', True, None) - self.config.add('branch', '', True, None) - self.config.add('cst_module_name', '', True, None) - self.config.add('copy_repo', '', True, None) - self.config.add('giturl', '', True, None) - self.config.add('repo_whl', '', True, None) - self.config.init_values() - - def emit_firstresult(self, *args: Any) -> None: - pass - - -class AutosummaryEntry(NamedTuple): - name: str - path: str - template: str - recursive: bool - - -def setup_documenters(app: Any) -> None: - from sphinx.ext.autodoc import (AttributeDocumenter, ClassDocumenter, DataDocumenter, - DecoratorDocumenter, ExceptionDocumenter, - FunctionDocumenter, MethodDocumenter, ModuleDocumenter, - NewTypeAttributeDocumenter, NewTypeDataDocumenter, - PropertyDocumenter) - documenters: List[Type[Documenter]] = [ - ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter, - FunctionDocumenter, MethodDocumenter, NewTypeAttributeDocumenter, - NewTypeDataDocumenter, AttributeDocumenter, DecoratorDocumenter, PropertyDocumenter, - ] - for documenter in documenters: - app.registry.add_documenter(documenter.objtype, documenter) - - -def _simple_info(msg: str) -> None: - warnings.warn('_simple_info() is deprecated.', - RemovedInSphinx50Warning, stacklevel=2) - print(msg) - - -def _simple_warn(msg: str) -> None: - warnings.warn('_simple_warn() is deprecated.', - RemovedInSphinx50Warning, stacklevel=2) - print('WARNING: ' + msg, file=sys.stderr) - - -def _underline(title: str, line: str = '=') -> str: - if '\n' in title: - raise ValueError('Can only underline single lines') - return title + '\n' + line * len(title) - - -class AutosummaryRenderer: - """A helper class for rendering.""" - - def __init__(self, app: Union[Builder, Sphinx], template_dir: str = None) -> None: - if isinstance(app, Builder): - warnings.warn('The first argument for AutosummaryRenderer has been ' - 'changed to Sphinx object', - RemovedInSphinx50Warning, stacklevel=2) - if template_dir: - warnings.warn('template_dir argument for AutosummaryRenderer is deprecated.', - RemovedInSphinx50Warning, stacklevel=2) - - system_templates_path = [os.path.join(package_dir, 'ext', 'autosummary', 'templates')] - loader = SphinxTemplateLoader(app.srcdir, app.config.templates_path, - system_templates_path) - - self.env = SandboxedEnvironment(loader=loader) - self.env.filters['escape'] = rst.escape - self.env.filters['e'] = rst.escape - self.env.filters['underline'] = _underline - - if isinstance(app, (Sphinx, DummyApplication)): - if app.translator: - self.env.add_extension("jinja2.ext.i18n") - self.env.install_gettext_translations(app.translator) - elif isinstance(app, Builder): - if app.app.translator: - self.env.add_extension("jinja2.ext.i18n") - self.env.install_gettext_translations(app.app.translator) - - def exists(self, template_name: str) -> bool: - """Check if template file exists.""" - warnings.warn('AutosummaryRenderer.exists() is deprecated.', - RemovedInSphinx50Warning, stacklevel=2) - try: - self.env.get_template(template_name) - return True - except TemplateNotFound: - return False - - def render(self, template_name: str, context: Dict) -> str: - """Render a template file.""" - try: - template = self.env.get_template(template_name) - except TemplateNotFound: - try: - # objtype is given as template_name - template = self.env.get_template('autosummary/%s.rst' % template_name) - except TemplateNotFound: - # fallback to base.rst - template = self.env.get_template('autosummary/base.rst') - - return template.render(context) - - -# -- Generating output --------------------------------------------------------- - - -class ModuleScanner: - def __init__(self, app: Any, obj: Any) -> None: - self.app = app - self.object = obj - - def get_object_type(self, name: str, value: Any) -> str: - return get_documenter(self.app, value, self.object).objtype - - def is_skipped(self, name: str, value: Any, objtype: str) -> bool: - try: - return self.app.emit_firstresult('autodoc-skip-member', objtype, - name, value, False, {}) - except Exception as exc: - logger.warning(__('autosummary: failed to determine %r to be documented, ' - 'the following exception was raised:\n%s'), - name, exc, type='autosummary') - return False - - def scan(self, imported_members: bool) -> List[str]: - members = [] - for name in members_of(self.object, self.app.config): - try: - value = safe_getattr(self.object, name) - except AttributeError: - value = None - - objtype = self.get_object_type(name, value) - if self.is_skipped(name, value, objtype): - continue - - try: - if inspect.ismodule(value): - imported = True - elif safe_getattr(value, '__module__') != self.object.__name__: - imported = True - else: - imported = False - except AttributeError: - imported = False - - respect_module_all = not self.app.config.autosummary_ignore_module_all - if imported_members: - # list all members up - members.append(name) - elif imported is False: - # list not-imported members - members.append(name) - elif '__all__' in dir(self.object) and respect_module_all: - # list members that have __all__ set - members.append(name) - - return members - - -def members_of(obj: Any, conf: Config) -> Sequence[str]: - """Get the members of ``obj``, possibly ignoring the ``__all__`` module attribute - - Follows the ``conf.autosummary_ignore_module_all`` setting.""" - - if conf.autosummary_ignore_module_all: - return dir(obj) - else: - return getall(obj) or dir(obj) - - -def generate_autosummary_content(name: str, obj: Any, parent: Any, - template: AutosummaryRenderer, template_name: str, - imported_members: bool, app: Any, - recursive: bool, context: Dict, - modname: str = None, qualname: str = None) -> str: - doc = get_documenter(app, obj, parent) - - def skip_member(obj: Any, name: str, objtype: str) -> bool: - try: - return app.emit_firstresult('autodoc-skip-member', objtype, name, - obj, False, {}) - except Exception as exc: - logger.warning(__('autosummary: failed to determine %r to be documented, ' - 'the following exception was raised:\n%s'), - name, exc, type='autosummary') - return False - - def get_class_members(obj: Any) -> Dict[str, Any]: - members = sphinx.ext.autodoc.get_class_members(obj, [qualname], safe_getattr) - return {name: member.object for name, member in members.items()} - - def get_module_members(obj: Any) -> Dict[str, Any]: - members = {} - for name in members_of(obj, app.config): - try: - members[name] = safe_getattr(obj, name) - except AttributeError: - continue - return members - - def get_all_members(obj: Any) -> Dict[str, Any]: - if doc.objtype == "module": - return get_module_members(obj) - elif doc.objtype == "class": - return get_class_members(obj) - return {} - - def get_members(obj: Any, types: Set[str], include_public: List[str] = [], - imported: bool = True) -> Tuple[List[str], List[str]]: - items: List[str] = [] - public: List[str] = [] - - all_members = get_all_members(obj) - for name, value in all_members.items(): - documenter = get_documenter(app, value, obj) - if documenter.objtype in types: - # skip imported members if expected - if imported or getattr(value, '__module__', None) == obj.__name__: - skipped = skip_member(value, name, documenter.objtype) - if skipped is True: - pass - elif skipped is False: - # show the member forcedly - items.append(name) - public.append(name) - else: - items.append(name) - if name in include_public or not name.startswith('_'): - # considers member as public - public.append(name) - return public, items - - def get_module_attrs(members: Any) -> Tuple[List[str], List[str]]: - """Find module attributes with docstrings.""" - attrs, public = [], [] - try: - analyzer = ModuleAnalyzer.for_module(name) - attr_docs = analyzer.find_attr_docs() - for namespace, attr_name in attr_docs: - if namespace == '' and attr_name in members: - attrs.append(attr_name) - if not attr_name.startswith('_'): - public.append(attr_name) - except PycodeError: - pass # give up if ModuleAnalyzer fails to parse code - return public, attrs - - def get_modules(obj: Any) -> Tuple[List[str], List[str]]: - items: List[str] = [] - for _, modname, _ispkg in pkgutil.iter_modules(obj.__path__): - fullname = name + '.' + modname - try: - module = import_module(fullname) - if module and hasattr(module, '__sphinx_mock__'): - continue - except ImportError: - pass - - items.append(fullname) - public = [x for x in items if not x.split('.')[-1].startswith('_')] - return public, items - - ns: Dict[str, Any] = {} - ns.update(context) - - if doc.objtype == 'module': - scanner = ModuleScanner(app, obj) - ns['members'] = scanner.scan(imported_members) - ns['functions'], ns['all_functions'] = \ - get_members(obj, {'function'}, imported=imported_members) - ns['classes'], ns['all_classes'] = \ - get_members(obj, {'class'}, imported=imported_members) - ns['exceptions'], ns['all_exceptions'] = \ - get_members(obj, {'exception'}, imported=imported_members) - ns['attributes'], ns['all_attributes'] = \ - get_module_attrs(ns['members']) - ispackage = hasattr(obj, '__path__') - if ispackage and recursive: - ns['modules'], ns['all_modules'] = get_modules(obj) - elif doc.objtype == 'class': - ns['members'] = dir(obj) - ns['inherited_members'] = \ - set(dir(obj)) - set(obj.__dict__.keys()) - ns['methods'], ns['all_methods'] = \ - get_members(obj, {'method'}, ['__init__']) - ns['attributes'], ns['all_attributes'] = \ - get_members(obj, {'attribute', 'property'}) - - if modname is None or qualname is None: - modname, qualname = split_full_qualified_name(name) - - if doc.objtype in ('method', 'attribute', 'property'): - ns['class'] = qualname.rsplit(".", 1)[0] - - if doc.objtype in ('class',): - shortname = qualname - else: - shortname = qualname.rsplit(".", 1)[-1] - - ns['fullname'] = name - ns['module'] = modname - ns['objname'] = qualname - ns['name'] = shortname - - ns['objtype'] = doc.objtype - ns['underline'] = len(name) * '=' - - if template_name: - return template.render(template_name, ns) - else: - return template.render(doc.objtype, ns) - - -def generate_autosummary_docs(sources: List[str], output_dir: str = None, - suffix: str = '.rst', base_path: str = None, - builder: Builder = None, template_dir: str = None, - imported_members: bool = False, app: Any = None, - overwrite: bool = True, encoding: str = 'utf-8') -> None: - - if builder: - warnings.warn('builder argument for generate_autosummary_docs() is deprecated.', - RemovedInSphinx50Warning, stacklevel=2) - - if template_dir: - warnings.warn('template_dir argument for generate_autosummary_docs() is deprecated.', - RemovedInSphinx50Warning, stacklevel=2) - - showed_sources = list(sorted(sources)) - if len(showed_sources) > 20: - showed_sources = showed_sources[:10] + ['...'] + showed_sources[-10:] - logger.info(__('[autosummary] generating autosummary for: %s') % - ', '.join(showed_sources)) - - if output_dir: - logger.info(__('[autosummary] writing to %s') % output_dir) - - if base_path is not None: - sources = [os.path.join(base_path, filename) for filename in sources] - - template = AutosummaryRenderer(app) - - # read - items = find_autosummary_in_files(sources) - - # keep track of new files - new_files = [] - - if app: - filename_map = app.config.autosummary_filename_map - else: - filename_map = {} - - # write - for entry in sorted(set(items), key=str): - if entry.path is None: - # The corresponding autosummary:: directive did not have - # a :toctree: option - continue - - path = output_dir or os.path.abspath(entry.path) - ensuredir(path) - - try: - name, obj, parent, modname = import_by_name(entry.name, grouped_exception=True) - qualname = name.replace(modname + ".", "") - except ImportExceptionGroup as exc: - try: - # try to import as an instance attribute - name, obj, parent, modname = import_ivar_by_name(entry.name) - qualname = name.replace(modname + ".", "") - except ImportError as exc2: - if exc2.__cause__: - exceptions: List[BaseException] = exc.exceptions + [exc2.__cause__] - else: - exceptions = exc.exceptions + [exc2] - - errors = list(set("* %s: %s" % (type(e).__name__, e) for e in exceptions)) - logger.warning(__('[autosummary] failed to import %s.\nPossible hints:\n%s'), - entry.name, '\n'.join(errors)) - continue - - context: Dict[str, Any] = {} - if app: - context.update(app.config.autosummary_context) - - content = generate_autosummary_content(name, obj, parent, template, entry.template, - imported_members, app, entry.recursive, context, - modname, qualname) - try: - py_source_rel = get_full_modname(modname, qualname).replace('.', '/') + '.py' - except: - logger.warning(name) - py_source_rel = '' - - re_view = f"\n.. image:: https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/{app.config.docs_branch}/" + \ - f"resource/_static/logo_source_en.svg\n :target: " + app.config.giturl + \ - f"{app.config.copy_repo}/blob/{app.config.branch}/" + app.config.repo_whl + \ - py_source_rel.split(app.config.cst_module_name)[-1] + '\n :alt: View Source On Gitee\n\n' - - if re_view not in content and py_source_rel: - content = re.sub('([=]{5,})\n', r'\1\n' + re_view, content, 1) - filename = os.path.join(path, filename_map.get(name, name) + suffix) - if os.path.isfile(filename): - with open(filename, encoding=encoding) as f: - old_content = f.read() - - if content == old_content: - continue - elif overwrite: # content has changed - with open(filename, 'w', encoding=encoding) as f: - f.write(content) - new_files.append(filename) - else: - with open(filename, 'w', encoding=encoding) as f: - f.write(content) - new_files.append(filename) - - # descend recursively to new files - if new_files: - generate_autosummary_docs(new_files, output_dir=output_dir, - suffix=suffix, base_path=base_path, - builder=builder, template_dir=template_dir, - imported_members=imported_members, app=app, - overwrite=overwrite) - - -# -- Finding documented entries in files --------------------------------------- - -def find_autosummary_in_files(filenames: List[str]) -> List[AutosummaryEntry]: - """Find out what items are documented in source/*.rst. - - See `find_autosummary_in_lines`. - """ - documented: List[AutosummaryEntry] = [] - for filename in filenames: - with open(filename, encoding='utf-8', errors='ignore') as f: - lines = f.read().splitlines() - documented.extend(find_autosummary_in_lines(lines, filename=filename)) - return documented - - -def find_autosummary_in_docstring(name: str, module: str = None, filename: str = None - ) -> List[AutosummaryEntry]: - """Find out what items are documented in the given object's docstring. - - See `find_autosummary_in_lines`. - """ - if module: - warnings.warn('module argument for find_autosummary_in_docstring() is deprecated.', - RemovedInSphinx50Warning, stacklevel=2) - - try: - real_name, obj, parent, modname = import_by_name(name, grouped_exception=True) - lines = pydoc.getdoc(obj).splitlines() - return find_autosummary_in_lines(lines, module=name, filename=filename) - except AttributeError: - pass - except ImportExceptionGroup as exc: - errors = list(set("* %s: %s" % (type(e).__name__, e) for e in exc.exceptions)) - print('Failed to import %s.\nPossible hints:\n%s' % (name, '\n'.join(errors))) - except SystemExit: - print("Failed to import '%s'; the module executes module level " - "statement and it might call sys.exit()." % name) - return [] - - -def find_autosummary_in_lines(lines: List[str], module: str = None, filename: str = None - ) -> List[AutosummaryEntry]: - """Find out what items appear in autosummary:: directives in the - given lines. - - Returns a list of (name, toctree, template) where *name* is a name - of an object and *toctree* the :toctree: path of the corresponding - autosummary directive (relative to the root of the file name), and - *template* the value of the :template: option. *toctree* and - *template* ``None`` if the directive does not have the - corresponding options set. - """ - autosummary_re = re.compile(r'^(\s*)\.\.\s+(ms[a-z]*)?autosummary::\s*') - automodule_re = re.compile( - r'^\s*\.\.\s+automodule::\s*([A-Za-z0-9_.]+)\s*$') - module_re = re.compile( - r'^\s*\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$') - autosummary_item_re = re.compile(r'^\s+(~?[_a-zA-Z][a-zA-Z0-9_.]*)\s*.*?') - recursive_arg_re = re.compile(r'^\s+:recursive:\s*$') - toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$') - template_arg_re = re.compile(r'^\s+:template:\s*(.*?)\s*$') - - documented: List[AutosummaryEntry] = [] - - recursive = False - toctree: str = None - template = None - current_module = module - in_autosummary = False - base_indent = "" - - for line in lines: - if in_autosummary: - m = recursive_arg_re.match(line) - if m: - recursive = True - continue - - m = toctree_arg_re.match(line) - if m: - toctree = m.group(1) - if filename: - toctree = os.path.join(os.path.dirname(filename), - toctree) - continue - - m = template_arg_re.match(line) - if m: - template = m.group(1).strip() - continue - - if line.strip().startswith(':'): - continue # skip options - - m = autosummary_item_re.match(line) - if m: - name = m.group(1).strip() - if name.startswith('~'): - name = name[1:] - if current_module and \ - not name.startswith(current_module + '.'): - name = "%s.%s" % (current_module, name) - documented.append(AutosummaryEntry(name, toctree, template, recursive)) - continue - - if not line.strip() or line.startswith(base_indent + " "): - continue - - in_autosummary = False - - m = autosummary_re.match(line) - if m: - in_autosummary = True - base_indent = m.group(1) - recursive = False - toctree = None - template = None - continue - - m = automodule_re.search(line) - if m: - current_module = m.group(1).strip() - # recurse into the automodule docstring - documented.extend(find_autosummary_in_docstring( - current_module, filename=filename)) - continue - - m = module_re.match(line) - if m: - current_module = m.group(2) - continue - - return documented - - -def get_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser( - usage='%(prog)s [OPTIONS] ...', - epilog=__('For more information, visit .'), - description=__(""" -Generate ReStructuredText using autosummary directives. - -sphinx-autogen is a frontend to sphinx.ext.autosummary.generate. It generates -the reStructuredText files from the autosummary directives contained in the -given input files. - -The format of the autosummary directive is documented in the -``sphinx.ext.autosummary`` Python module and can be read using:: - - pydoc sphinx.ext.autosummary -""")) - - parser.add_argument('--version', action='version', dest='show_version', - version='%%(prog)s %s' % __display_version__) - - parser.add_argument('source_file', nargs='+', - help=__('source files to generate rST files for')) - - parser.add_argument('-o', '--output-dir', action='store', - dest='output_dir', - help=__('directory to place all output in')) - parser.add_argument('-s', '--suffix', action='store', dest='suffix', - default='rst', - help=__('default suffix for files (default: ' - '%(default)s)')) - parser.add_argument('-t', '--templates', action='store', dest='templates', - default=None, - help=__('custom template directory (default: ' - '%(default)s)')) - parser.add_argument('-i', '--imported-members', action='store_true', - dest='imported_members', default=False, - help=__('document imported members (default: ' - '%(default)s)')) - parser.add_argument('-a', '--respect-module-all', action='store_true', - dest='respect_module_all', default=False, - help=__('document exactly the members in module __all__ attribute. ' - '(default: %(default)s)')) - - return parser - - -def main(argv: List[str] = sys.argv[1:]) -> None: - sphinx.locale.setlocale(locale.LC_ALL, '') - sphinx.locale.init_console(os.path.join(package_dir, 'locale'), 'sphinx') - translator, _ = sphinx.locale.init([], None) - - app = DummyApplication(translator) - logging.setup(app, sys.stdout, sys.stderr) # type: ignore - setup_documenters(app) - args = get_parser().parse_args(argv) - - if args.templates: - app.config.templates_path.append(path.abspath(args.templates)) - app.config.autosummary_ignore_module_all = not args.respect_module_all # type: ignore - - generate_autosummary_docs(args.source_file, args.output_dir, - '.' + args.suffix, - imported_members=args.imported_members, - app=app) - - -if __name__ == '__main__': - main() diff --git a/docs/sciai/docs/_ext/overwriteobjectiondirective.txt b/docs/sciai/docs/_ext/overwriteobjectiondirective.txt deleted file mode 100644 index e7ffdfe09a..0000000000 --- a/docs/sciai/docs/_ext/overwriteobjectiondirective.txt +++ /dev/null @@ -1,374 +0,0 @@ -""" - sphinx.directives - ~~~~~~~~~~~~~~~~~ - - Handlers for additional ReST directives. - - :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" - -import re -import inspect -import importlib -from functools import reduce -from typing import TYPE_CHECKING, Any, Dict, Generic, List, Tuple, TypeVar, cast - -from docutils import nodes -from docutils.nodes import Node -from docutils.parsers.rst import directives, roles - -from sphinx import addnodes -from sphinx.addnodes import desc_signature -from sphinx.deprecation import RemovedInSphinx50Warning, deprecated_alias -from sphinx.util import docutils, logging -from sphinx.util.docfields import DocFieldTransformer, Field, TypedField -from sphinx.util.docutils import SphinxDirective -from sphinx.util.typing import OptionSpec - -if TYPE_CHECKING: - from sphinx.application import Sphinx - - -# RE to strip backslash escapes -nl_escape_re = re.compile(r'\\\n') -strip_backslash_re = re.compile(r'\\(.)') - -T = TypeVar('T') -logger = logging.getLogger(__name__) - -def optional_int(argument: str) -> int: - """ - Check for an integer argument or None value; raise ``ValueError`` if not. - """ - if argument is None: - return None - else: - value = int(argument) - if value < 0: - raise ValueError('negative value; must be positive or zero') - return value - -def get_api(fullname): - """ - 获取接口对象。 - - :param fullname: 接口名全称 - :return: 属性对象或None(如果不存在) - """ - main_module = fullname.split('.')[0] - main_import = importlib.import_module(main_module) - - try: - return reduce(getattr, fullname.split('.')[1:], main_import) - except AttributeError: - return None - -def get_example(name: str): - try: - api_doc = inspect.getdoc(get_api(name)) - example_str = re.findall(r'Examples:\n([\w\W]*?)(\n\n|$)', api_doc) - if not example_str: - return [] - example_str = re.sub(r'\n\s+', r'\n', example_str[0][0]) - example_str = example_str.strip() - example_list = example_str.split('\n') - return ["", "**样例:**", ""] + example_list + [""] - except: - return [] - -def get_platforms(name: str): - try: - api_doc = inspect.getdoc(get_api(name)) - example_str = re.findall(r'Supported Platforms:\n\s+(.*?)\n\n', api_doc) - if not example_str: - example_str_leak = re.findall(r'Supported Platforms:\n\s+(.*)', api_doc) - if example_str_leak: - example_str = example_str_leak[0].strip() - example_list = example_str.split('\n') - example_list = [' ' + example_list[0]] - return ["", "支持平台:"] + example_list + [""] - return [] - example_str = example_str[0].strip() - example_list = example_str.split('\n') - example_list = [' ' + example_list[0]] - return ["", "支持平台:"] + example_list + [""] - except: - return [] - -class ObjectDescription(SphinxDirective, Generic[T]): - """ - Directive to describe a class, function or similar object. Not used - directly, but subclassed (in domain-specific directives) to add custom - behavior. - """ - - has_content = True - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = True - option_spec: OptionSpec = { - 'noindex': directives.flag, - } # type: Dict[str, DirectiveOption] - - # types of doc fields that this directive handles, see sphinx.util.docfields - doc_field_types: List[Field] = [] - domain: str = None - objtype: str = None - indexnode: addnodes.index = None - - # Warning: this might be removed in future version. Don't touch this from extensions. - _doc_field_type_map = {} # type: Dict[str, Tuple[Field, bool]] - - def get_field_type_map(self) -> Dict[str, Tuple[Field, bool]]: - if self._doc_field_type_map == {}: - self._doc_field_type_map = {} - for field in self.doc_field_types: - for name in field.names: - self._doc_field_type_map[name] = (field, False) - - if field.is_typed: - typed_field = cast(TypedField, field) - for name in typed_field.typenames: - self._doc_field_type_map[name] = (field, True) - - return self._doc_field_type_map - - def get_signatures(self) -> List[str]: - """ - Retrieve the signatures to document from the directive arguments. By - default, signatures are given as arguments, one per line. - - Backslash-escaping of newlines is supported. - """ - lines = nl_escape_re.sub('', self.arguments[0]).split('\n') - if self.config.strip_signature_backslash: - # remove backslashes to support (dummy) escapes; helps Vim highlighting - return [strip_backslash_re.sub(r'\1', line.strip()) for line in lines] - else: - return [line.strip() for line in lines] - - def handle_signature(self, sig: str, signode: desc_signature) -> Any: - """ - Parse the signature *sig* into individual nodes and append them to - *signode*. If ValueError is raised, parsing is aborted and the whole - *sig* is put into a single desc_name node. - - The return value should be a value that identifies the object. It is - passed to :meth:`add_target_and_index()` unchanged, and otherwise only - used to skip duplicates. - """ - raise ValueError - - def add_target_and_index(self, name: Any, sig: str, signode: desc_signature) -> None: - """ - Add cross-reference IDs and entries to self.indexnode, if applicable. - - *name* is whatever :meth:`handle_signature()` returned. - """ - return # do nothing by default - - def before_content(self) -> None: - """ - Called before parsing content. Used to set information about the current - directive context on the build environment. - """ - pass - - def transform_content(self, contentnode: addnodes.desc_content) -> None: - """ - Called after creating the content through nested parsing, - but before the ``object-description-transform`` event is emitted, - and before the info-fields are transformed. - Can be used to manipulate the content. - """ - pass - - def after_content(self) -> None: - """ - Called after parsing content. Used to reset information about the - current directive context on the build environment. - """ - pass - - def check_class_end(self, content): - for i in content: - if not i.startswith('.. include::') and i != "\n" and i != "": - return False - return True - - def extend_items(self, rst_file, start_num, num): - ls = [] - for i in range(1, num+1): - ls.append((rst_file, start_num+i)) - return ls - - def run(self) -> List[Node]: - """ - Main directive entry function, called by docutils upon encountering the - directive. - - This directive is meant to be quite easily subclassable, so it delegates - to several additional methods. What it does: - - * find out if called as a domain-specific directive, set self.domain - * create a `desc` node to fit all description inside - * parse standard options, currently `noindex` - * create an index node if needed as self.indexnode - * parse all given signatures (as returned by self.get_signatures()) - using self.handle_signature(), which should either return a name - or raise ValueError - * add index entries using self.add_target_and_index() - * parse the content and handle doc fields in it - """ - if ':' in self.name: - self.domain, self.objtype = self.name.split(':', 1) - else: - self.domain, self.objtype = '', self.name - self.indexnode = addnodes.index(entries=[]) - - node = addnodes.desc() - node.document = self.state.document - node['domain'] = self.domain - # 'desctype' is a backwards compatible attribute - node['objtype'] = node['desctype'] = self.objtype - node['noindex'] = noindex = ('noindex' in self.options) - if self.domain: - node['classes'].append(self.domain) - node['classes'].append(node['objtype']) - - self.names: List[T] = [] - signatures = self.get_signatures() - for sig in signatures: - # add a signature node for each signature in the current unit - # and add a reference target for it - signode = addnodes.desc_signature(sig, '') - self.set_source_info(signode) - node.append(signode) - try: - # name can also be a tuple, e.g. (classname, objname); - # this is strictly domain-specific (i.e. no assumptions may - # be made in this base class) - name = self.handle_signature(sig, signode) - except ValueError: - # signature parsing failed - signode.clear() - signode += addnodes.desc_name(sig, sig) - continue # we don't want an index entry here - if name not in self.names: - self.names.append(name) - if not noindex: - # only add target and index entry if this is the first - # description of the object with this name in this desc block - self.add_target_and_index(name, sig, signode) - - contentnode = addnodes.desc_content() - node.append(contentnode) - if self.names: - # needed for association of version{added,changed} directives - self.env.temp_data['object'] = self.names[0] - self.before_content() - try: - example = get_example(self.names[0][0]) - platforms = get_platforms(self.names[0][0]) - except Exception as e: - example = '' - platforms = '' - logger.warning(f'Error API names in {self.arguments[0]}.') - logger.warning(f'{e}') - extra = platforms + example - if extra: - if self.objtype == "method": - self.content.data.extend(extra) - else: - index_num = 0 - for num, i in enumerate(self.content.data): - if i.startswith('.. py:method::') or self.check_class_end(self.content.data[num:]): - index_num = num - break - if index_num: - count = len(self.content.data) - for i in extra: - self.content.data.insert(index_num-count, i) - else: - self.content.data.extend(extra) - try: - self.content.items.extend(self.extend_items(self.content.items[0][0], self.content.items[-1][1], len(extra))) - except Exception as e: - logger.warning(f'{e}') - self.state.nested_parse(self.content, self.content_offset, contentnode) - self.transform_content(contentnode) - self.env.app.emit('object-description-transform', - self.domain, self.objtype, contentnode) - DocFieldTransformer(self).transform_all(contentnode) - self.env.temp_data['object'] = None - self.after_content() - return [self.indexnode, node] - - -class DefaultRole(SphinxDirective): - """ - Set the default interpreted text role. Overridden from docutils. - """ - - optional_arguments = 1 - final_argument_whitespace = False - - def run(self) -> List[Node]: - if not self.arguments: - docutils.unregister_role('') - return [] - role_name = self.arguments[0] - role, messages = roles.role(role_name, self.state_machine.language, - self.lineno, self.state.reporter) - if role: - docutils.register_role('', role) - self.env.temp_data['default_role'] = role_name - else: - literal_block = nodes.literal_block(self.block_text, self.block_text) - reporter = self.state.reporter - error = reporter.error('Unknown interpreted text role "%s".' % role_name, - literal_block, line=self.lineno) - messages += [error] - - return cast(List[nodes.Node], messages) - - -class DefaultDomain(SphinxDirective): - """ - Directive to (re-)set the default domain for this source file. - """ - - has_content = False - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = False - option_spec = {} # type: Dict - - def run(self) -> List[Node]: - domain_name = self.arguments[0].lower() - # if domain_name not in env.domains: - # # try searching by label - # for domain in env.domains.values(): - # if domain.label.lower() == domain_name: - # domain_name = domain.name - # break - self.env.temp_data['default_domain'] = self.env.domains.get(domain_name) - return [] - -def setup(app: "Sphinx") -> Dict[str, Any]: - app.add_config_value("strip_signature_backslash", False, 'env') - directives.register_directive('default-role', DefaultRole) - directives.register_directive('default-domain', DefaultDomain) - directives.register_directive('describe', ObjectDescription) - # new, more consistent, name - directives.register_directive('object', ObjectDescription) - - app.add_event('object-description-transform') - - return { - 'version': 'builtin', - 'parallel_read_safe': True, - 'parallel_write_safe': True, - } - diff --git a/docs/sciai/docs/_ext/overwriteviewcode.txt b/docs/sciai/docs/_ext/overwriteviewcode.txt deleted file mode 100644 index 172780ec56..0000000000 --- a/docs/sciai/docs/_ext/overwriteviewcode.txt +++ /dev/null @@ -1,378 +0,0 @@ -""" - sphinx.ext.viewcode - ~~~~~~~~~~~~~~~~~~~ - - Add links to module code in Python object descriptions. - - :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" - -import posixpath -import traceback -import warnings -from os import path -from typing import Any, Dict, Generator, Iterable, Optional, Set, Tuple, cast - -from docutils import nodes -from docutils.nodes import Element, Node - -import sphinx -from sphinx import addnodes -from sphinx.application import Sphinx -from sphinx.builders import Builder -from sphinx.builders.html import StandaloneHTMLBuilder -from sphinx.deprecation import RemovedInSphinx50Warning -from sphinx.environment import BuildEnvironment -from sphinx.locale import _, __ -from sphinx.pycode import ModuleAnalyzer -from sphinx.transforms.post_transforms import SphinxPostTransform -from sphinx.util import get_full_modname, logging, status_iterator -from sphinx.util.nodes import make_refnode - - -logger = logging.getLogger(__name__) - - -OUTPUT_DIRNAME = '_modules' - - -class viewcode_anchor(Element): - """Node for viewcode anchors. - - This node will be processed in the resolving phase. - For viewcode supported builders, they will be all converted to the anchors. - For not supported builders, they will be removed. - """ - - -def _get_full_modname(app: Sphinx, modname: str, attribute: str) -> Optional[str]: - try: - return get_full_modname(modname, attribute) - except AttributeError: - # sphinx.ext.viewcode can't follow class instance attribute - # then AttributeError logging output only verbose mode. - logger.verbose('Didn\'t find %s in %s', attribute, modname) - return None - except Exception as e: - # sphinx.ext.viewcode follow python domain directives. - # because of that, if there are no real modules exists that specified - # by py:function or other directives, viewcode emits a lot of warnings. - # It should be displayed only verbose mode. - logger.verbose(traceback.format_exc().rstrip()) - logger.verbose('viewcode can\'t import %s, failed with error "%s"', modname, e) - return None - - -def is_supported_builder(builder: Builder) -> bool: - if builder.format != 'html': - return False - elif builder.name == 'singlehtml': - return False - elif builder.name.startswith('epub') and not builder.config.viewcode_enable_epub: - return False - else: - return True - - -def doctree_read(app: Sphinx, doctree: Node) -> None: - env = app.builder.env - if not hasattr(env, '_viewcode_modules'): - env._viewcode_modules = {} # type: ignore - - def has_tag(modname: str, fullname: str, docname: str, refname: str) -> bool: - entry = env._viewcode_modules.get(modname, None) # type: ignore - if entry is False: - return False - - code_tags = app.emit_firstresult('viewcode-find-source', modname) - if code_tags is None: - try: - analyzer = ModuleAnalyzer.for_module(modname) - analyzer.find_tags() - except Exception: - env._viewcode_modules[modname] = False # type: ignore - return False - - code = analyzer.code - tags = analyzer.tags - else: - code, tags = code_tags - - if entry is None or entry[0] != code: - entry = code, tags, {}, refname - env._viewcode_modules[modname] = entry # type: ignore - _, tags, used, _ = entry - if fullname in tags: - used[fullname] = docname - return True - - return False - - for objnode in list(doctree.findall(addnodes.desc)): - if objnode.get('domain') != 'py': - continue - names: Set[str] = set() - for signode in objnode: - if not isinstance(signode, addnodes.desc_signature): - continue - modname = signode.get('module') - fullname = signode.get('fullname') - try: - if fullname and modname==None: - if fullname.split('.')[-1].lower() == fullname.split('.')[-1] and fullname.split('.')[-2].lower() != fullname.split('.')[-2]: - modname = '.'.join(fullname.split('.')[:-2]) - fullname = '.'.join(fullname.split('.')[-2:]) - else: - modname = '.'.join(fullname.split('.')[:-1]) - fullname = fullname.split('.')[-1] - fullname_new = fullname - except Exception: - logger.warning(f'error_modename:{modname}') - logger.warning(f'error_fullname:{fullname}') - refname = modname - if env.config.viewcode_follow_imported_members: - new_modname = app.emit_firstresult( - 'viewcode-follow-imported', modname, fullname, - ) - if not new_modname: - new_modname = _get_full_modname(app, modname, fullname) - modname = new_modname - # logger.warning(f'new_modename:{modname}') - if not modname: - continue - # fullname = signode.get('fullname') - # if fullname and modname==None: - fullname = fullname_new - if not has_tag(modname, fullname, env.docname, refname): - continue - if fullname in names: - # only one link per name, please - continue - names.add(fullname) - pagename = posixpath.join(OUTPUT_DIRNAME, modname.replace('.', '/')) - signode += viewcode_anchor(reftarget=pagename, refid=fullname, refdoc=env.docname) - - -def env_merge_info(app: Sphinx, env: BuildEnvironment, docnames: Iterable[str], - other: BuildEnvironment) -> None: - if not hasattr(other, '_viewcode_modules'): - return - # create a _viewcode_modules dict on the main environment - if not hasattr(env, '_viewcode_modules'): - env._viewcode_modules = {} # type: ignore - # now merge in the information from the subprocess - for modname, entry in other._viewcode_modules.items(): # type: ignore - if modname not in env._viewcode_modules: # type: ignore - env._viewcode_modules[modname] = entry # type: ignore - else: - if env._viewcode_modules[modname]: # type: ignore - used = env._viewcode_modules[modname][2] # type: ignore - for fullname, docname in entry[2].items(): - if fullname not in used: - used[fullname] = docname - - -def env_purge_doc(app: Sphinx, env: BuildEnvironment, docname: str) -> None: - modules = getattr(env, '_viewcode_modules', {}) - - for modname, entry in list(modules.items()): - if entry is False: - continue - - code, tags, used, refname = entry - for fullname in list(used): - if used[fullname] == docname: - used.pop(fullname) - - if len(used) == 0: - modules.pop(modname) - - -class ViewcodeAnchorTransform(SphinxPostTransform): - """Convert or remove viewcode_anchor nodes depends on builder.""" - default_priority = 100 - - def run(self, **kwargs: Any) -> None: - if is_supported_builder(self.app.builder): - self.convert_viewcode_anchors() - else: - self.remove_viewcode_anchors() - - def convert_viewcode_anchors(self) -> None: - for node in self.document.findall(viewcode_anchor): - anchor = nodes.inline('', _('[源代码]'), classes=['viewcode-link']) - refnode = make_refnode(self.app.builder, node['refdoc'], node['reftarget'], - node['refid'], anchor) - node.replace_self(refnode) - - def remove_viewcode_anchors(self) -> None: - for node in list(self.document.findall(viewcode_anchor)): - node.parent.remove(node) - - -def missing_reference(app: Sphinx, env: BuildEnvironment, node: Element, contnode: Node - ) -> Optional[Node]: - # resolve our "viewcode" reference nodes -- they need special treatment - if node['reftype'] == 'viewcode': - warnings.warn('viewcode extension is no longer use pending_xref node. ' - 'Please update your extension.', RemovedInSphinx50Warning) - return make_refnode(app.builder, node['refdoc'], node['reftarget'], - node['refid'], contnode) - - return None - - -def get_module_filename(app: Sphinx, modname: str) -> Optional[str]: - """Get module filename for *modname*.""" - source_info = app.emit_firstresult('viewcode-find-source', modname) - if source_info: - return None - else: - try: - filename, source = ModuleAnalyzer.get_module_source(modname) - return filename - except Exception: - return None - - -def should_generate_module_page(app: Sphinx, modname: str) -> bool: - """Check generation of module page is needed.""" - module_filename = get_module_filename(app, modname) - if module_filename is None: - # Always (re-)generate module page when module filename is not found. - return True - - builder = cast(StandaloneHTMLBuilder, app.builder) - basename = modname.replace('.', '/') + builder.out_suffix - page_filename = path.join(app.outdir, '_modules/', basename) - - try: - if path.getmtime(module_filename) <= path.getmtime(page_filename): - # generation is not needed if the HTML page is newer than module file. - return False - except IOError: - pass - - return True - - -def collect_pages(app: Sphinx) -> Generator[Tuple[str, Dict[str, Any], str], None, None]: - env = app.builder.env - if not hasattr(env, '_viewcode_modules'): - return - if not is_supported_builder(app.builder): - return - highlighter = app.builder.highlighter # type: ignore - urito = app.builder.get_relative_uri - - modnames = set(env._viewcode_modules) # type: ignore - - for modname, entry in status_iterator( - sorted(env._viewcode_modules.items()), # type: ignore - __('highlighting module code... '), "blue", - len(env._viewcode_modules), # type: ignore - app.verbosity, lambda x: x[0]): - if not entry: - continue - if not should_generate_module_page(app, modname): - continue - - code, tags, used, refname = entry - # construct a page name for the highlighted source - pagename = posixpath.join(OUTPUT_DIRNAME, modname.replace('.', '/')) - # highlight the source using the builder's highlighter - if env.config.highlight_language in ('python3', 'default', 'none'): - lexer = env.config.highlight_language - else: - lexer = 'python' - highlighted = highlighter.highlight_block(code, lexer, linenos=False) - # split the code into lines - lines = highlighted.splitlines() - # split off wrap markup from the first line of the actual code - before, after = lines[0].split('
')
-        lines[0:1] = [before + '
', after]
-        # nothing to do for the last line; it always starts with 
anyway - # now that we have code lines (starting at index 1), insert anchors for - # the collected tags (HACK: this only works if the tag boundaries are - # properly nested!) - maxindex = len(lines) - 1 - for name, docname in used.items(): - type, start, end = tags[name] - backlink = urito(pagename, docname) + '#' + refname + '.' + name - lines[start] = ( - '
%s' % (name, backlink, _('[文档]')) + - lines[start]) - lines[min(end, maxindex)] += '
' - # try to find parents (for submodules) - parents = [] - parent = modname - while '.' in parent: - parent = parent.rsplit('.', 1)[0] - if parent in modnames: - parents.append({ - 'link': urito(pagename, - posixpath.join(OUTPUT_DIRNAME, parent.replace('.', '/'))), - 'title': parent}) - parents.append({'link': urito(pagename, posixpath.join(OUTPUT_DIRNAME, 'index')), - 'title': _('Module code')}) - parents.reverse() - # putting it all together - context = { - 'parents': parents, - 'title': modname, - 'body': (_('

Source code for %s

') % modname + - '\n'.join(lines)), - } - yield (pagename, context, 'page.html') - - if not modnames: - return - - html = ['\n'] - # the stack logic is needed for using nested lists for submodules - stack = [''] - for modname in sorted(modnames): - if modname.startswith(stack[-1]): - stack.append(modname + '.') - html.append('
    ') - else: - stack.pop() - while not modname.startswith(stack[-1]): - stack.pop() - html.append('
') - stack.append(modname + '.') - html.append('
  • %s
  • \n' % ( - urito(posixpath.join(OUTPUT_DIRNAME, 'index'), - posixpath.join(OUTPUT_DIRNAME, modname.replace('.', '/'))), - modname)) - html.append('' * (len(stack) - 1)) - context = { - 'title': _('Overview: module code'), - 'body': (_('

    All modules for which code is available

    ') + - ''.join(html)), - } - - yield (posixpath.join(OUTPUT_DIRNAME, 'index'), context, 'page.html') - - -def setup(app: Sphinx) -> Dict[str, Any]: - app.add_config_value('viewcode_import', None, False) - app.add_config_value('viewcode_enable_epub', False, False) - app.add_config_value('viewcode_follow_imported_members', True, False) - app.connect('doctree-read', doctree_read) - app.connect('env-merge-info', env_merge_info) - app.connect('env-purge-doc', env_purge_doc) - app.connect('html-collect-pages', collect_pages) - app.connect('missing-reference', missing_reference) - # app.add_config_value('viewcode_include_modules', [], 'env') - # app.add_config_value('viewcode_exclude_modules', [], 'env') - app.add_event('viewcode-find-source') - app.add_event('viewcode-follow-imported') - app.add_post_transform(ViewcodeAnchorTransform) - return { - 'version': sphinx.__display_version__, - 'env_version': 1, - 'parallel_read_safe': True - } diff --git a/docs/sciai/docs/requirements.txt b/docs/sciai/docs/requirements.txt deleted file mode 100644 index a1b6a69f6d..0000000000 --- a/docs/sciai/docs/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -sphinx == 4.4.0 -docutils == 0.17.1 -myst-parser == 0.18.1 -sphinx_rtd_theme == 1.0.0 -numpy -IPython -jieba diff --git a/docs/sciai/docs/source_en/_templates/classtemplate.rst b/docs/sciai/docs/source_en/_templates/classtemplate.rst deleted file mode 100644 index 37a8e95499..0000000000 --- a/docs/sciai/docs/source_en/_templates/classtemplate.rst +++ /dev/null @@ -1,27 +0,0 @@ -.. role:: hidden - :class: hidden-section - -.. currentmodule:: {{ module }} - -{% if objname in [] %} -{{ fullname | underline }} - -.. autofunction:: {{ fullname }} - -{% elif objname[0].istitle() %} -{{ fullname | underline }} - -.. autoclass:: {{ name }} - :exclude-members: construct - :members: - -{% else %} -{{ fullname | underline }} - -.. autofunction:: {{ fullname }} - -{% endif %} - -.. - autogenerated from _templates/classtemplate.rst - note it does not have :inherited-members: diff --git a/docs/sciai/docs/source_en/build_model_with_sciai.md b/docs/sciai/docs/source_en/build_model_with_sciai.md deleted file mode 100644 index b337f9f60d..0000000000 --- a/docs/sciai/docs/source_en/build_model_with_sciai.md +++ /dev/null @@ -1,240 +0,0 @@ -# Building Neural Networks with SciAI - -[![View Source On Gitee](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source_en.svg)](https://gitee.com/mindspore/docs/blob/master/docs/sciai/docs/source_en/build_model_with_sciai.md)   - -SciAI base framework consists of several modules covering network setup, network training, validation and auxiliary functions. - -The following examples indicates the fundamental processes in using SciAI to build a neural network model. - -> You can download the full sample code here: -> - -## Model Building Basics - -The principle of setting up a neural network in ScAI is the same as in [MindSpore](https://www.mindspore.cn/tutorials/en/master/beginner/model.html), but in SciAI it is much easier. - -This chapter takes a Multi-Layer Percetron(MLP) as example, introduces how to train a network to solve the following equation. - -$$ -f(x) = {x_1}^2 + sin(x_2) -$$ - -For the codes of this part, please refer to the [codes](https://gitee.com/mindspore/mindscience/blob/master/SciAI/tutorial/example_net.py). - -### Setup Neural Networks - -The following code segment creates a multi-layer perceptron with 2-D input, 1-D output and two 5-D hidden layers. - -```python -from sciai.architecture import MLP -from sciai.common.initializer import XavierTruncNormal - -net = MLP(layers=[2, 5, 5, 1], weight_init=XavierTruncNormal(), bias_init='zeros', activation="tanh") -``` - -`MLP` will use normal distribution to initialize the weights, and initialize bias with zeros by default. The activation function is `tanh` by default. - -At meantime, `MLP` accepts various initialization method and all [activation functions](https://www.mindspore.cn/docs/en/master/api_python/mindspore.nn.html) provided by MindSpore, as well as those designed for scientific computing. - -### Loss Definition - -We define the loss function as a sub-class of [Cell](https://www.mindspore.cn/docs/en/master/api_python/nn/mindspore.nn.Cell.html), and calculate the loss in method `construct`. - -```python -from mindspore import nn -from sciai.architecture import MSE - -class ExampleLoss(nn.Cell): - def __init__(self, network): - super().__init__() - self.network = network - self.mse = MSE() - - def construct(self, x, y_true): - y_predict = self.network(x) - return self.mse(y_predict - y_true) - -net_loss = ExampleLoss(net) -``` - -The current loss predicted by `net` can be calculated by calling `net_loss` directly and taking the input `x` as the parameter with the true value `y_true`. - -```python -from mindspore import Tensor - -x = Tensor([[0.5, 0.5]]) -y_true = Tensor([0.72942554]) -print("loss value: ", net_loss(x, y_true)) -# expected output -... -loss value: 0.3026065 -``` - -### Model Training and Evaluation - -Then, by creating instance of trainer class provided by SciAI, we can start training with datasets. -In this case, we randomly sample the equation mentioned above to generate dataset `x_train` and `y_true` for training. - -The code segment for training is given as follows, indicating several abilities of SciAI. -The trainer class `TrainCellWithCallBack` is similar to [MindSpore.nn.TrainOneStepCell](https://www.mindspore.cn/docs/en/master/api_python/nn/mindspore.nn.TrainOneStepCell.html), -which needs network `net_loss` and optimizer as parameters and provides callbacks for scientific computation. -Callbacks include printing loss values and time consumption during training and automatic `ckpt` files saving. -The following code wll print the `loss` and time consumption every 100 epochs and save the current model as `ckpt` file every 1000 epochs. -SciAI provides the tool `to_tensor`, which converts multiple numpy data to `Tensor` conveniently. -Use `log_config` to specify the target directory for automatically saving the `TrainCellWithCallBack` callback printouts, as well as those printed by the user using `print_log`. - -```python -import numpy as np -from mindspore import nn -from sciai.common import TrainCellWithCallBack -from sciai.context.context import init_project -from sciai.utils import to_tensor, print_log, log_config - -# Get the correct platform automatically and set to GRAPH_MODE by default. -init_project() -# Auto log saving -log_config("./logs") - -def func(x): - """The function to be learned to""" - return x[:, 0:1] ** 2 + np.sin(x[:, 1:2]) - -optimizer = nn.Adam(net_loss.trainable_params()) -trainer = TrainCellWithCallBack(net_loss, optimizer, loss_interval=100, time_interval=100, ckpt_interval=1000) -x_train = np.random.rand(1000, 2) -# Randomly collect ground truth -y_true = func(x_train) -# Convert to Tensor data type -x_train, y_true = to_tensor((x_train, y_true)) -for _ in range(10001): - trainer(x_train, y_true) -print_log("Finished") -``` - -The expected output is as follows. - -```bash -python ./example_net.py -# expected output -... -step: 0, loss: 0.5189553, interval: 2.7039313316345215s, total: 2.7039313316345215s -step: 100, loss: 0.080132075, interval: 0.11984062194824219s, total: 2.8237719535827637s -step: 200, loss: 0.055663396, interval: 0.09104156494140625s, total: 2.91481351852417s -step: 300, loss: 0.032194577, interval: 0.09095025062561035s, total: 3.0057637691497803s -step: 400, loss: 0.015914217, interval: 0.09099435806274414s, total: 3.0967581272125244s -... -Finished -``` - -When the training of `net` is finished and loss converges, we can use the net to predict the value at `x` by calling `y = net(x)`. -Continue to randomly sample a number of positions `x_val` for validation. - -```python -x_val = np.random.rand(5, 2) -y_true = func(x_val) -y_pred = net(to_tensor(x_val)).asnumpy() -print_log("y_true:") -print_log(y_true) -print_log("y_pred:") -print_log(y_pred) -``` - -The expected output is as follows. After training, the predicted values are close to those obtained by numerical calculation. - -```bash -# expected output -y_true: -[[0.34606973] - [0.70457536] - [0.90531053] - [0.84420218] - [0.48239506]] -y_pred: -[[0.34271246] - [0.70356864] - [0.89893466] - [0.8393946 ] - [0.47805673]] -``` - -## Model Building Extension - -User can solve more complicated problems with SciAI, for example Physics-Informed Neural Network(PINN). This chapter introduces how to use MLP to solve the following Partial Differential Equation(PDE) with SciAI. - -$$ -\frac{\partial{f}}{\partial{x}} - 2 \frac{f}{x} + {x}^2 {y}^2 = 0 -$$ - -The boundary conditions are defined to be - -$$ -f(0) = 0, f(1) = 1. -$$ - -Under those boundary conditions, the analytic solution of this PDE is - -$$ -f(x) = \frac{x^2}{0.2 x^5 + 0.8}. -$$ - -For the codes of this part, please refer to [codes](https://gitee.com/mindspore/mindscience/blob/master/SciAI/tutorial/example_grad_net.py). - -### Loss Definition - -Similar to the loss definition in the last chapter, the loss should be defined as a child class of [Cell](https://www.mindspore.cn/docs/en/master/api_python/nn/mindspore.nn.Cell.html). - -The difference is that in this loss function, the partial derivative of the original function needs to be calculated. -SciAI provides tool `operators.grad` for this situation. Through setting the input and output index, we can calculate the derivative of certain inputs w.r.t. certain output. -In this problem, the dimensions of input and output are 1, therefore, we set `input_index` and `output_index` to 0. - -```python -from mindspore import nn, ops -from sciai.architecture import MSE, MLP -from sciai.operators import grad - -class ExampleLoss(nn.Cell): - """ Loss definition class""" - def __init__(self, network): - super().__init__() - self.network = network - self.dy_dx = grad(net=self.network, output_index=0, input_index=0) # partial differential definition - self.mse = MSE() - - def construct(self, x, x_bc, y_bc_true): - y = self.network(x) - dy_dx = self.dy_dx(x) - domain_res = dy_dx - 2 * ops.div(y, x) + ops.mul(ops.pow(x, 2), ops.pow(y, 2)) # PDE residual error - - y_bc = self.network(x_bc) - bc_res = y_bc_true - y_bc # Boundary conditions residual - return self.mse(domain_res) + 10 * self.mse(bc_res) -``` - -### Model Training and Evaluation - -Executing training and evaluation by launching the script in the terminal, we can get the following expected outputs. The predictions `y_pred` are close to the true values `y_true`. - -```bash -python ./example_grad_net.py -# expected output -... -step: 0, loss: 3.1961572, interval: 3.117840051651001s, total: 3.117840051651001s -step: 100, loss: 1.0862937, interval: 0.23533344268798828s, total: 3.353173494338989s -step: 200, loss: 0.7334847, interval: 0.21307134628295898s, total: 3.566244840621948s -step: 300, loss: 0.5629723, interval: 0.19696831703186035s, total: 3.763213157653809s -step: 400, loss: 0.4133342, interval: 0.20153212547302246s, total: 3.964745283126831s -... -Finished -y_true: -[[0.02245186] - [0.99459697] - [0.04027248] - [0.12594332] - [0.39779923]] -y_pred: -[[0.02293926] - [0.99337316] - [0.03924912] - [0.12166673] - [0.4006738 ]] -``` \ No newline at end of file diff --git a/docs/sciai/docs/source_en/conf.py b/docs/sciai/docs/source_en/conf.py deleted file mode 100644 index 87fd487bd8..0000000000 --- a/docs/sciai/docs/source_en/conf.py +++ /dev/null @@ -1,272 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os -import shutil -import sys -import IPython -import re -import sphinx -sys.path.append(os.path.abspath('../_ext')) -import sphinx.ext.autosummary.generate as g -from sphinx.ext import autodoc as sphinx_autodoc - -# -- Project information ----------------------------------------------------- - -project = 'MindSpore SciAI' -copyright = 'MindSpore' -author = 'MindSpore' - -# The full version, including alpha/beta/rc tags -release = 'master' - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -myst_enable_extensions = ["dollarmath", "amsmath"] - - -myst_heading_anchors = 5 -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.doctest', - 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', - 'sphinx.ext.napoleon', - 'sphinx.ext.viewcode', - 'myst_parser', - 'sphinx.ext.mathjax', - 'IPython.sphinxext.ipython_console_highlighting' -] - -source_suffix = { - '.rst': 'restructuredtext', - '.md': 'markdown', -} - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -mathjax_path = 'https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/mathjax/MathJax-3.2.2/es5/tex-mml-chtml.js' - -mathjax_options = { - 'async':'async' -} - -smartquotes_action = 'De' - -exclude_patterns = [] - -pygments_style = 'sphinx' - -autodoc_inherit_docstrings = False - -autosummary_generate = True - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'sphinx_rtd_theme' - -import sphinx_rtd_theme -layout_target = os.path.join(os.path.dirname(sphinx_rtd_theme.__file__), 'layout.html') -layout_src = '../../../../resource/_static/layout.html' -if os.path.exists(layout_target): - os.remove(layout_target) -shutil.copy(layout_src, layout_target) - -html_search_language = 'en' - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - 'python': ('https://docs.python.org/3', '../../../../resource/python_objects.inv'), -} - -# overwriteautosummary_generate add view source for api and more autosummary class availably. -with open('../_ext/overwriteautosummary_generate.txt', 'r', encoding="utf8") as f: - exec(f.read(), g.__dict__) - -# Modify default signatures for autodoc. -autodoc_source_path = os.path.abspath(sphinx_autodoc.__file__) -autodoc_source_re = re.compile(r'stringify_signature\(.*?\)') -get_param_func_str = r"""\ -import re -import inspect as inspect_ - -def remove_typehints_content(text): - # 初始化括号匹配标记,0为无括号包裹 - bracket_count = 0 - start_idx = -1 # 记录第一个":"的位置 - - for i, char in enumerate(text): - # 1. 找到第一个":",记录起始位置 - if start_idx == -1 and char == ":": - start_idx = i - continue - - # 2. 已找到":",开始判断括号状态 - if start_idx != -1: - # 遇到"("或"[",括号计数+1(进入括号内) - if char in ("(", "["): - bracket_count += 1 - # 遇到")"或"]",括号计数-1(离开括号内) - elif char in (")", "]"): - bracket_count = max(0, bracket_count - 1) # 避免负数值 - # 3. 找到不在括号内的第一个",",执行删除 - elif char == "," and bracket_count == 0: - return text[:start_idx] + text[i:] # 拼接删除后的内容 - # 4. 找到不在括号内的第一个"=",执行删除 - elif char == "=" and bracket_count == 0: - return text[:start_idx] + " " + text[i:] # 拼接删除后的内容,"="前需要有一个空格 - - # 若未找到目标",",返回原文本 - return text - -def get_param_func(func): - try: - source_code = inspect_.getsource(func) - if func.__doc__: - source_code = source_code.replace(func.__doc__, '') - all_params_str = re.findall(r"def [\w_\d\-]+\(([\S\s]*?)(\):|\) ->.*?:)", source_code) - all_params = re.sub("(self|cls)(,|, )?", '', all_params_str[0][0].replace("\n", "").replace("'", "\"")) - - if ":" in all_params: - colon_idx = all_params.find(":") - # 处理非最后一个":"以后的内容 - while colon_idx != -1 and "," in all_params[colon_idx+1:]: - all_params = remove_typehints_content(all_params) - # 最后一个":"以后的内容中包含"," - if colon_idx == all_params.find(":"): - break - colon_idx = all_params.find(":") - - # 去掉最后一个":"以后的内容 - colon_idx = all_params.find(":") - if colon_idx != -1: - # 最后一个":"以后的内容中包含"=",需要保留"="及以后的内容 - if "=" in all_params[colon_idx+1:]: - all_params = re.sub(":(.*?)=", ' =', all_params) - # 正常删除最后一个":"以后的内容 - else: - all_params = re.sub(":.*$", '', all_params) - # 目前仅有lambda x出现在最后的情况 - if all_params.endswith("lambda x"): - all_params += ": ..." - - return all_params - except: - return '' - -def get_obj(obj): - if isinstance(obj, type): - return obj.__init__ - - return obj -""" - -with open(autodoc_source_path, "r+", encoding="utf8") as f: - code_str = f.read() - code_str = autodoc_source_re.sub('"(" + get_param_func(get_obj(self.object)) + ")"', code_str, count=0) - exec(get_param_func_str, sphinx_autodoc.__dict__) - exec(code_str, sphinx_autodoc.__dict__) - -# Copy source files of en python api from sciai repository. -import shutil -from sphinx.util import logging -logger = logging.getLogger(__name__) - -src_dir = os.path.join(os.getenv("MSC_PATH"), 'docs/api_python_en/sciai') - -if not os.path.exists(src_dir): - logger.warning("There is no source dir in sciai repository.") -else: - src_files = os.listdir(src_dir) - for i in os.listdir(src_dir): - if os.path.isfile(os.path.join(src_dir,i)): - if os.path.exists('./'+i): - os.remove('./'+i) - shutil.copy(os.path.join(src_dir,i),'./'+i) - else: - if os.path.exists('./'+i): - shutil.rmtree('./'+i) - shutil.copytree(os.path.join(src_dir,i),'./'+i) - -# get params for add view source -import json - -if os.path.exists('../../../../tools/generate_html/version.json'): - with open('../../../../tools/generate_html/version.json', 'r+', encoding='utf-8') as f: - version_inf = json.load(f) -elif os.path.exists('../../../../tools/generate_html/daily_dev.json'): - with open('../../../../tools/generate_html/daily_dev.json', 'r+', encoding='utf-8') as f: - version_inf = json.load(f) -elif os.path.exists('../../../../tools/generate_html/daily.json'): - with open('../../../../tools/generate_html/daily.json', 'r+', encoding='utf-8') as f: - version_inf = json.load(f) - -if os.getenv("MSC_PATH").split('/')[-1]: - copy_repo = os.getenv("MSC_PATH").split('/')[-1] -else: - copy_repo = os.getenv("MSC_PATH").split('/')[-2] - -branch = [version_inf[i]['branch'] for i in range(len(version_inf)) if version_inf[i]['name'] == copy_repo][0] -docs_branch = [version_inf[i]['branch'] for i in range(len(version_inf)) if version_inf[i]['name'] == 'tutorials'][0] -cst_module_name = 'sciai' -repo_whl = 'SciAI/sciai' -giturl = 'https://gitee.com/mindspore/' - -import sciai - -sys.path.append(os.path.abspath('../../../../resource/sphinx_ext')) -# import nbsphinx_mod - -sys.path.append(os.path.abspath('../../../../resource/search')) -import search_code - -sys.path.append(os.path.abspath('../../../../resource/custom_directives')) -from custom_directives import IncludeCodeDirective - -from myautosummary import MsPlatformAutoSummary, MsCnPlatformAutoSummary - -def setup(app): - app.add_directive('msplatformautosummary', MsPlatformAutoSummary) - app.add_directive('mscnplatformautosummary', MsCnPlatformAutoSummary) - app.add_directive('includecode', IncludeCodeDirective) - app.add_config_value('docs_branch', '', True) - app.add_config_value('branch', '', True) - app.add_config_value('cst_module_name', '', True) - app.add_config_value('copy_repo', '', True) - app.add_config_value('giturl', '', True) - app.add_config_value('repo_whl', '', True) - -src_release = os.path.join(os.getenv("MSC_PATH"), 'SciAI/RELEASE.md') -des_release = "./RELEASE.md" -with open(src_release, "r", encoding="utf-8") as f: - data = f.read() -if len(re.findall("\n## (.*?)\n",data)) > 1: - content = re.findall("(## [\s\S\n]*?)\n## ", data) -else: - content = re.findall("(## [\s\S\n]*)", data) -#result = content[0].replace('# MindFlow', '#', 1) -with open(des_release, "w", encoding="utf-8") as p: - p.write("# Release Notes"+"\n\n") - p.write(content[0]) \ No newline at end of file diff --git a/docs/sciai/docs/source_en/images/architecture.png b/docs/sciai/docs/source_en/images/architecture.png deleted file mode 100644 index 17ff9d3972e4e0daedb2989a6d8a144e1cd81384..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55443 zcmce;2UL?w*EWpDBNjwN1di0BC{;kDNmmh(CcTCtAe{sWkkBI{A}F9jK)Un}QbPzu zx`ZaZBmpU*C!vSVm!Ri)p7;I#cm3b`*ZRJ!m2f-vJu`b|@7a4_*UW90&Qn$T3v3r? zXlUrwo;=c{p*h1#LvtEfsOo? z68^R?*TWuXwDI%uubs2e!M^|g!;*~(xD81`guuf zL`?nt)a%Q7+z*iFe^q&XIVSO+`u|zTj^{mTlJcVi`ltOr|FiJ_z21K`ru$#(t$&~0 z9@0Nsf3+;Py#=WGlTTX(%9))2X0)bV!emfT^s!E-1UD;1h<*wp9bypyu%Jad+o7PKS>~tt=pmt~0L5 z7}i5;OpAmnh9JacLIM2Lipsg`C&TT(tDhim;*`e4u>oG$`LQ+>Ko1=mbtR_vEYUx- zoLp1ZHzZ=>*7fEh{j)RrNVldI4zP(#+KynorgKO?0?Y!&zmwyVbP%@GdIC(}RWT_GGIfc|V~t>0tN zGsag9Tu$D%H2ErwS47yoAGd9etR?bRI(9e@9ky(}ad$YlY@)~F zYH_hJTfzP>OZkaiT7YAu}^udOU_;cndKhp1HDLB-sfii z**Aav`cr;j9#-kO=CHu@&k#B7yqujH-GJ=B1JpDdF7YEwFBm^^RFJwMwfoXH!8h$@ z(rB{$h#{T68(Oey);M6G4bqfs1mWeDzuBLiz{p1_^aBtZ*MpjG^Uz_JX z-{O;afyXLYem0F^s5lWk-{SPB^f>(C#&}R-&c=m!#qJ)JOOV=sKw()|a%cK^N^gGix`oUJ+p`}iumDO{1nnhamzjOh z(e1E$5PY&CsY=g$5aVauBR_N>+t}8Wnex&Z{Me|rSr6G@dPN{|25zz*v7VEoZ)>QO z{MmPWtJkm{AxXm`M<7zZ zQ}1G6NZ~+z#oFBNX#qN0+Sf9k&1qJDp(N@S`hl>gGY}QabpxN$;tx9tH7<}mehWlG z9FOb$u72QL>T>`Rs1@J_X1q`(9N|;%r+T=scS_6!3|nPM4a=XDHM*_%My9@|q1c<- zYRJm#;G_MP=D+oVi;vo@EFEA_&zSLJ^FQ79eYH9HZf- z%9ff^@c~87$LaH3*&L)h;AWA6>>Y)TN_}S;+S}s*>ydl(fsIQ^-UC~0zM7hni4Ta| zP!!80;!oRjQeIcxbnHuA}maX&hB3HRsJZi6raxh;J6WIOc!yXNGf;E~78EsY$&v9*lH*J&LIF4sk zLc8&mP4jqzeFNfE!n&)v%2gv3cH+5};4TmU%0AJFwU7|g99M{OiEM2XS>@alq@+H| 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�k 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 diff --git a/docs/sciai/docs/source_en/index.rst b/docs/sciai/docs/source_en/index.rst deleted file mode 100644 index 2575b7c988..0000000000 --- a/docs/sciai/docs/source_en/index.rst +++ /dev/null @@ -1,52 +0,0 @@ -Introduction to SciAI -===================== - -Based on MindSpore, SciAI is a model library with 60 built-in most frequently used and cited AI4Sci(AI for Science) models, which cover SOTA models from physics-informed (PINNs, DeepRitz, PFNN, etc.) to neural operators (FNO, DeepONet, PDENet), ranking No.1 in the world in terms of coverage. -MindSpore SciAI provides the developers and users with a high-level API (auto configuration, auto instantiation, training and fine-tuning, etc.), allowing an immediate deployment. -With these features, MindSpore SciAI covers a wide variety of scientific computation fields, including fluid dynamics, electromagnetism, sound, heat, solid and biology, providing developers and users with an efficient and convenient AI4SCI computation platform. - -.. raw:: html - - - -.. toctree:: - :maxdepth: 1 - :caption: Installation - - installation - -.. toctree:: - :maxdepth: 1 - :caption: Launching Instruction - - launch_with_scripts - launch_with_api - -.. toctree:: - :maxdepth: 1 - :caption: Model Library - - model_library - -.. toctree:: - :maxdepth: 1 - :caption: Tutorial - - build_model_with_sciai - -.. toctree:: - :maxdepth: 1 - :caption: API Reference - - sciai.architecture - sciai.common - sciai.context - sciai.operators - sciai.utils - -.. toctree:: - :glob: - :maxdepth: 1 - :caption: RELEASE NOTES - - RELEASE diff --git a/docs/sciai/docs/source_en/installation.md b/docs/sciai/docs/source_en/installation.md deleted file mode 100644 index 8120de79c0..0000000000 --- a/docs/sciai/docs/source_en/installation.md +++ /dev/null @@ -1,74 +0,0 @@ -# MindSpore SciAI Installation - -[![View Source On Gitee](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source_en.svg)](https://gitee.com/mindspore/docs/blob/master/docs/sciai/docs/source_en/installation.md) -   - -## System Environment Information Confirmation - -- The hardware platform should be Ascend or GPU. -- See [MindSpore Installation Guide](https://www.mindspore.cn/install/en) to install MindSpore. - The versions of MindSpore Elec and MindSpore must be consistent. -- All other dependencies are included - in [requirements.txt](https://gitee.com/mindspore/mindscience/blob/master/SciAI/requirements.txt). - -## Installation - -You can install MindSpore SciAI either by pip or by source code. - -### Method 1: Install With Pip - -This method installs SciAI from .whl package automatically downloaded from MindSpore website, -which does not require the download and compilation of source code. - -```bash -pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.2.0/MindScience/sciai/gpu/{arch}/cuda-11.1/sciai-{version}-cp37-cp37m-linux_{arch}.whl -i https://pypi.tuna.tsinghua.edu.cn/simple -``` - -> - When the network is connected, dependencies of the SciAI installation package are automatically downloaded during - the .whl package installation. For details about dependencies, see setup.py. -> - {version} denotes the version of SciAI. For example, when you are installing SciAI 0.1.0, {version} should - be `0.1.0`. -> - {arch} denotes the system architecture. For example, the Linux system you are using is x86 architecture 64-bit, - {arch} should be `x86_64`. If the system is ARM architecture 64-bit, then it should be `aarch64`. - -The following table provides the corresponding installation commands to each architecture and Python version. - -| Device | Architecture | Python | Command | -|--------|--------------|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Ascend | x86_64 | Python=3.7 | `pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.2.0/MindScience/sciai/gpu/x86_64/cuda-11.1/sciai-0.1.0-cp37-cp37m-linux_x86_64.whl -i https://pypi.tuna.tsinghua.edu.cn/simple` | -| | aarch64 | Python=3.7 | `pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.2.0/MindScience/sciai/ascend/aarch64/sciai-0.1.0-cp37-cp37m-linux_aarch64.whl -i https://pypi.tuna.tsinghua.edu.cn/simple` | -| GPU | x86_64 | Python=3.7 | `pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.2.0/MindScience/sciai/gpu/x86_64/cuda-11.1/sciai-0.1.0-cp37-cp37m-linux_x86_64.whl -i https://pypi.tuna.tsinghua.edu.cn/simple` | - -Note: If you have other MindScience package(s) installed in your conda or python env, such as `MindElec`, `MindFlow` -, `MindSponge`, please uninstall the MindScience package(s) in the environment first to avoid pip behavior conflicts. - -### Method 2: Install From Source Code - -1. Clone the source code from the Git repository of MindScience. - - ```bash - cd ~ - git clone https://gitee.com/mindspore/mindscience.git - ``` - -2. Build SciAI with script `build.sh`. - - ```bash - cd mindscience/SciAI - bash build.sh -j8 - ``` - -3. After the compilation is complete, install the compiled `.whl` package with the following command. - - ```bash - bash install.sh - ``` - -### Installation Verification - -To verify the installation, run the following commands. If the error message `No module named 'sciai'` is not displayed, -the installation is successful. - -```bash -python -c 'import sciai' -``` diff --git a/docs/sciai/docs/source_en/launch_with_api.md b/docs/sciai/docs/source_en/launch_with_api.md deleted file mode 100644 index 23f1517c51..0000000000 --- a/docs/sciai/docs/source_en/launch_with_api.md +++ /dev/null @@ -1,57 +0,0 @@ -# Launching Model with API - -[![View Source On Gitee](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source_en.svg)](https://gitee.com/mindspore/docs/blob/master/docs/sciai/docs/source_en/launch_with_api.md)   - -MindSpore SciAI provides users with a high order interface `AutoModel`, with which the supported model in the model library can be instantiated with one line code. - -User can launch training and evaluation process with `AutoModel`. - -## Obtaining the Network with AutoModel - -User can use the function `AutoModel.from_pretrained` to get the network models, which are supported in SciAI. - -Here we use the model Conservative Physics-Informed Neural Networks (CPINNs) as example. For the codes of CPINNs model, please refer to the [link](https://gitee.com/mindspore/mindscience/tree/master/SciAI/sciai/model/cpinns). - -The fundamental idea about this model can be found in this [paper](https://www.sciencedirect.com/science/article/abs/pii/S0045782520302127). - -```python -from sciai.model import AutoModel - -# obtain the cpinns model. -model = AutoModel.from_pretrained("cpinns") -``` - -## Training and Fine-tuning with AutoModel - -User can use the function `AutoModel.train` to train the neural networks, and before training, user can use `AutoModel.update_config` to configure the training parameters or finetune the model by loading the `.ckpt` file. - -The acceptable arguments for API `AutoModel.update_config` depends on the model instantiated. - -```python -from sciai.model import AutoModel - -# obtain the cpinns model. -model = AutoModel.from_pretrained("cpinns") -# (optional) load the ckpt file and initialize the model based on the loaded parameters. -model.update_config(load_ckpt=True, load_ckpt_path="./checkpoints/your_file.ckpt", epochs=500) -# train the network with default configuration, -# the figures, data and logs generated will be saved in your execution path. -model.train() -``` - -## Evaluating with AutoModel - -User can evaluate the trained networks with function `AutoModel.evaluate`. - -This function will load the `.ckpt` files provided in SciAI by default. Alternatively, user can load their own `.ckpt` file with interface `AutoModel.update_config`. - -```python -from sciai.model import AutoModel - -# obtain the cpinns model -model = AutoModel.from_pretrained("cpinns") -# (optional) load the ckpt file provided by user -model.update_config(load_ckpt=True, load_ckpt_path="./checkpoints/your_file.ckpt") -# evaluate the model -model.evaluate() -``` diff --git a/docs/sciai/docs/source_en/launch_with_scripts.md b/docs/sciai/docs/source_en/launch_with_scripts.md deleted file mode 100644 index 5fc05c2dd4..0000000000 --- a/docs/sciai/docs/source_en/launch_with_scripts.md +++ /dev/null @@ -1,64 +0,0 @@ -# Launching Model with Scripts - -[![View Source On Gitee](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source_en.svg)](https://gitee.com/mindspore/docs/blob/master/docs/sciai/docs/source_en/launch_with_scripts.md)   - -The models in MindSpore SciAI provides users with scripts for training and evaluation. - -User can train or evaluate any model by running scripts, and the model parameters can be adjusted either through editing the config file or passing parameters in the command line. [This folder](https://gitee.com/mindspore/mindscience/tree/master/SciAI/sciai/model) contains all the models that support launching with scripts. - -The following content introduces the general process of training, evaluating models with scripts, taking Conservative Physics-Informed Neural Networks(CPINNs) as an example. For the codes of CPINNs model, please refer to the [link](https://gitee.com/mindspore/mindscience/tree/master/SciAI/sciai/model/cpinns). - -The fundamental idea about this model can be found in this [paper](https://www.sciencedirect.com/science/article/abs/pii/S0045782520302127). - -## Downloading the Repository - -User can clone the whole repository and initialize the environment variable `PYTHONPATH` with the following commands. - -```bash -git clone https://gitee.com/mindspore/mindscience -source ./mindscience/SciAI/.env -``` - -After a successful clone, user can start training or evaluating according to the `Quick Start` section in the [README.md](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/cpinns/README.md)(In case of CPINNs). - -```bash -cd ./mindscience/SciAI/sciai/model/cpinns/ -``` - -## Training and Fine-tuning the Model - -User can run script [train.py](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/cpinns/train.py) in each model directory to train the models. - -```bash -python ./train.py [--parameters] -# expected output -... -step: 0, loss1: 2.1404986, loss2: 8.205103, loss3: 37.23588, loss4: 3.56359, interval: 50.85803508758545s, total: 50.85803508758545s -step: 10, loss1: 2.6560388, loss2: 3.869413, loss3: 9.323585, loss4: 2.1194165, interval: 5.159524917602539s, total: 56.01756000518799s -step: 20, loss1: 1.7885156, loss2: 4.470225, loss3: 3.3072894, loss4: 1.5674783, interval: 1.8615927696228027s, total: 57.87915277481079s -... -``` - -Use the `.ckpt` file to finetune the network: - -```bash -python ./train.py --load_ckpt true --load_ckpt_path {your_file}.ckpt [--parameters] -``` - -Using the optional parameter `[--parameters]`, user can configure the training process of the model, including learning rate, training epochs, data saving and loading paths and so on. - -For details about the configurable parameters in each model, see the `Script Parameters` section in the [README.md](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/cpinns/README.md). - -## Evaluating the Model - -User can run script `eval.py` in each model directory to evaluate the trained networks. - -```bash -python ./eval.py [--parameters] -# expected output -... -error_u: 0.024803562642018585 -Total time running eval: 20.625872135162354 seconds -``` - -Using the optional parameter `[--parameters]`, user can configure the evaluation process of the model, including the data read and save paths, checkpoints file loading paths, and so on. \ No newline at end of file diff --git a/docs/sciai/docs/source_en/model_library.md b/docs/sciai/docs/source_en/model_library.md deleted file mode 100644 index b6f3ae4c1d..0000000000 --- a/docs/sciai/docs/source_en/model_library.md +++ /dev/null @@ -1,74 +0,0 @@ -# Model Library - -[![View Source On Gitee](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source_en.svg)](https://gitee.com/mindspore/docs/blob/master/docs/sciai/docs/source_en/model_library.md)   - -SciAI model library provides a wide variety of models that are frequently used and cited in scientific computation. -The following table summarizes the current available neural networks and their corresponding domains. - -| Domain | Network | MindSpore Implementation and Parameters | Ascend | GPU | -|---------------------|-----------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------:|:---:| -| General Physics | [auq_pinns](https://www.sciencedirect.com/science/article/pii/S0021999119303584) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/auq_pinns/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [cpinns](https://www.sciencedirect.com/science/article/abs/pii/S0045782520302127) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/cpinns/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [deep_hpms](https://www.jmlr.org/papers/volume19/18-046/18-046.pdf) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/deep_hpms/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [deep_ritz](https://arxiv.org/abs/1710.00211) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/deep_ritz/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [deepbsde](https://www.pnas.org/doi/10.1073/pnas.1718942115) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/deepbsde/README.md#script-parameters) | | ✅ | -| General Physics | [deeponet](https://www.nature.com/articles/s42256-021-00302-5) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/deeponet/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [dgm](https://arxiv.org/abs/1708.07469) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/dgm/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [fbsnns](https://arxiv.org/abs/1804.07010) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/fbsnns/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [fpinns](https://arxiv.org/abs/1811.08967) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/fpinns/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [gradient_pathologies_pinns](https://arxiv.org/abs/2001.04536) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/gradient_pathologies_pinns/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [hp_vpinns](https://arxiv.org/abs/2003.05385) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/hp_vpinns/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [laaf](https://doi.org/10.1016/j.jcp.2019.109136) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/laaf/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [mgnet](https://link.springer.com/article/10.1007/s11425-019-9547-2) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/mgnet/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [multiscale_pinns](https://www.sciencedirect.com/science/article/abs/pii/S0045782521002759) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/multiscale_pinns/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [pfnn](https://www.sciencedirect.com/science/article/abs/pii/S0021999120308597) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pfnn/README_CN.md#脚本说明) | | ✅ | -| General Physics | [phygeonet](https://www.sciencedirect.com/science/article/abs/pii/S0021999120308536) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/phygeonet/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [pi_deeponet](https://www.sciencedirect.com/science/article/abs/pii/S0021999122009184) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pi_deeponet/README.md#script-parameters) | | ✅ | -| General Physics | [pinns](https://www.sciencedirect.com/science/article/abs/pii/S0021999118307125) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinns/README.md#script-parameters) | | ✅ | -| General Physics | [pinns_ntk](https://www.sciencedirect.com/science/article/pii/S002199912100663X) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinns_ntk/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [ppinns](https://www.sciencedirect.com/science/article/abs/pii/S0045782520304357) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/ppinns/README.md#script-parameters) | ✅ | ✅ | -| General Physics | [xpinns](https://doi.org/10.4208/cicp.OA-2020-0164) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/xpinns/README.md#script-parameters) | ✅ | ✅ | -| Hamiltonian Systems | [sympnets](https://www.sciencedirect.com/science/article/pii/S0893608020303063) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/sympnets/README.md#script-parameters) | ✅ | ✅ | -| Fluid Dynamic | [hfm](https://www.science.org/doi/abs/10.1126/science.aaw4741) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/hfm/README.md#script-parameters) | ✅ | ✅ | -| Fluid Dynamic | [label_free_dnn_surrogate](https://www.sciencedirect.com/science/article/pii/S004578251930622X) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/label_free_dnn_surrogate/README.md#script-parameters) | ✅ | ✅ | -| Fluid Dynamic | [nsf_nets](https://www.sciencedirect.com/science/article/pii/S0021999120307257) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/nsf_nets/README.md#script-parameters) | ✅ | ✅ | -| Fluid Dynamic | [*burgers_fno](https://arxiv.org/abs/2010.08895) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_driven/burgers/fno1d/FNO1D.ipynb) | ✅ | ✅ | -| Fluid Dynamic | [*burgers_kno](https://arxiv.org/abs/2301.10022) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_driven/burgers/kno1d/KNO1D.ipynb) | ✅ | ✅ | -| Fluid Dynamic | [*navier_stokes_fno](https://arxiv.org/abs/2010.08895) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_driven/navier_stokes/fno2d/FNO2D.ipynb) | ✅ | ✅ | -| Fluid Dynamic | [*navier_stokes_kno](https://arxiv.org/abs/2301.10022) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_driven/navier_stokes/kno2d/KNO2D.ipynb) | ✅ | ✅ | -| Fluid Dynamic | [*navier_stokes_3d_fno](https://arxiv.org/abs/2010.08895) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_driven/navier_stokes/fno3d/FNO3D.ipynb) | ✅ | ✅ | -| Fluid Dynamic | [*pde_net](https://arxiv.org/abs/1710.09668) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_mechanism_fusion/pde_net/README.md) | ✅ | ✅ | -| Fluid Dynamic | [*percnn](https://www.nature.com/articles/s42256-023-00685-7) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_mechanism_fusion/percnn/README.md) | ✅ | ✅ | -| Elastodynamics | [pinn_elastodynamics](https://arxiv.org/abs/2006.08472) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinn_elastodynamics/README.md#script-parameters) | ✅ | ✅ | -| Thermodynamics | [pinn_heattransfer](https://arxiv.org/abs/1711.10561) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinn_heattransfer/README.md#script-parameters) | ✅ | ✅ | -| Meteorology | [enso](https://doi.org/10.1038/s41586-019-1559-7) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/enso/README.md#script-parameters) | ✅ | ✅ | -| Geology | [inversion_net](https://ieeexplore.ieee.org/abstract/document/8918045/) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/inversion_net/README.md#script-parameters) | ✅ | ✅ | -| Geology | [pinn_helmholtz](https://academic.oup.com/gji/article-abstract/228/3/1750/6409132) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinn_helmholtz/README.md#script-parameters) | ✅ | ✅ | -| Oceanic Physics | [ocean_model](https://gmd.copernicus.org/articles/12/4729/2019/) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/ocean_model/README.md#Model-Description) | | ✅ | -| Oceanic Physics | [pinns_swe](https://arxiv.org/abs/2104.00615) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinns_swe/README.md#script-parameters) | ✅ | ✅ | -| Electromagnetism | [maxwell_net](https://arxiv.org/abs/2107.06164) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/maxwell_net/README.md#script-parameters) | ✅ | ✅ | -| Electromagnetism | [*AD_FDTD_invert_f](https://www.mindspore.cn/mindelec/docs/en/r0.2/AD_FDTD.html) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/AD_FDTD/fdtd_forward/README.md#script-parameters) | | ✅ | -| Electromagnetism | [*AD_FDTD_microstrip_filter](https://www.mindspore.cn/mindelec/docs/en/r0.2/AD_FDTD.html) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/AD_FDTD/fdtd_forward/README.md#script-parameters) | | ✅ | -| Electromagnetism | [*AD_FDTD_inverse](https://www.mindspore.cn/mindelec/docs/en/r0.2/AD_FDTD.html) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/AD_FDTD/fdtd_inverse/README.md#script-parameters) | | ✅ | -| Electromagnetism | [*frequency_domain_maxwell](https://arxiv.org/abs/2107.06164) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/frequency_domain_maxwell/README.md#script-parameters) | ✅ | ✅ | -| Electromagnetism | [*frequency_domain_maxwell_3D_dielectric_slab](https://arxiv.org/abs/2107.06164) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/frequency_domain_maxwell_3D/dielectric_slab_3d/README.md#脚本参数) | ✅ | ✅ | -| Electromagnetism | [*frequency_domain_maxwell_3D_waveguide_cavity](https://arxiv.org/abs/2107.06164) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/frequency_domain_maxwell_3D/waveguide_cavity_3d/README.md#脚本参数) | ✅ | ✅ | -| Electromagnetism | [*meta_auto_decoder](https://arxiv.org/abs/2111.08823) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/incremental_learning/README.md#script-parameters) | ✅ | ✅ | -| Electromagnetism | [*pinn_fwi](https://agupubs.onlinelibrary.wiley.com/doi/abs/10.1029/2021JB023120) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/pinn_fwi/README.md) | ✅ | ✅ | -| Electromagnetism | [*SED_ANN](https://gitee.com/mindspore/mindscience/tree/master/MindElec/examples/data_driven/sed_ann) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/data_driven/sed_ann/README_CN.md) | ✅ | ✅ | -| Electromagnetism | [*time_domain_maxwell](https://www.ijcai.org/proceedings/2022/533) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/time_domain_maxwell/README.md#script-parameters) | ✅ | ✅ | -| Electromagnetism | [*metasurface_holograms](https://www.researching.cn/articles/OJ44d3746c3db8c1e1) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/metasurface/metasurface_holograms/README.md#parameters) | ✅ | ✅ | -| Biology | [*MEGA-Fold](https://arxiv.org/abs/2206.12240v1) | [link (inference)](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) [link (training)](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) | ✅ | ✅ | -| Biology | [*MEGA-EvoGen](https://arxiv.org/abs/2208.09652) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) | ✅ | ✅ | -| Biology | [*MEGA-Assessment](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) | [link (inference)](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) [link (training)](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) | ✅ | ✅ | -| Biology | [*ColabDesign](https://www.biorxiv.org/content/10.1101/2021.11.10.468128.abstract) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/ColabDesign.md) | ✅ | ✅ | -| Biology | [*DeepFRI](https://www.nature.com/articles/s41467-021-23303-9) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/DeepFri.md) | ✅ | ✅ | -| Biology | [*Multimer](https://www.biorxiv.org/content/10.1101/2021.10.04.463034v1) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/afmultimer.md) | ✅ | ✅ | -| Biology | [*ProteinMPNN](https://www.science.org/doi/abs/10.1126/science.add2187) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/ProteinMPNN.MD) | ✅ | ✅ | -| Biology | [*UFold](https://doi.org/10.1093/nar/gkab1074) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/UFold.md) | ✅ | ✅ | -| Biology | [*esm-if1](https://proceedings.mlr.press/v162/hsu22a.html) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/ESM-IF1.md) | ✅ | ✅ | -| Biology | [*esm2](https://www.biorxiv.org/content/10.1101/2022.07.20.500902v1.full.pdf) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/ESM-2.md) | ✅ | ✅ | -| Biology | [*grover](https://proceedings.neurips.cc/paper/2020/file/94aef38441efa3380a3bed3faf1f9d5d-Paper.pdf) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/GROVER.MD) | ✅ | ✅ | - -Note: the "*" in the model names indicates that these models have already been released at an earlier time by MindSpore -and MindScience. \ No newline at end of file diff --git a/docs/sciai/docs/source_zh_cn/_templates/classtemplate.rst b/docs/sciai/docs/source_zh_cn/_templates/classtemplate.rst deleted file mode 100644 index 37a8e95499..0000000000 --- a/docs/sciai/docs/source_zh_cn/_templates/classtemplate.rst +++ /dev/null @@ -1,27 +0,0 @@ -.. role:: hidden - :class: hidden-section - -.. currentmodule:: {{ module }} - -{% if objname in [] %} -{{ fullname | underline }} - -.. autofunction:: {{ fullname }} - -{% elif objname[0].istitle() %} -{{ fullname | underline }} - -.. autoclass:: {{ name }} - :exclude-members: construct - :members: - -{% else %} -{{ fullname | underline }} - -.. autofunction:: {{ fullname }} - -{% endif %} - -.. - autogenerated from _templates/classtemplate.rst - note it does not have :inherited-members: diff --git a/docs/sciai/docs/source_zh_cn/build_model_with_sciai.md b/docs/sciai/docs/source_zh_cn/build_model_with_sciai.md deleted file mode 100644 index 64430a4342..0000000000 --- a/docs/sciai/docs/source_zh_cn/build_model_with_sciai.md +++ /dev/null @@ -1,240 +0,0 @@ -# 使用SciAI构建神经网络 - -[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/sciai/docs/source_zh_cn/build_model_with_sciai.md)   - -SciAI基础框架由若干基础模块构成,涵盖有神经网络搭建、训练、验证以及其他辅助函数等。 - -如下的示例展示了使用SciAI构建神经网络模型并进行训练的流程。 - -> 你可以在这里下载完整的样例代码: -> - -## 模型构建基础 - -使用SciAI基础框架创建神经网络的原理与[使用MindSpore构建网络](https://www.mindspore.cn/tutorials/zh-CN/master/beginner/model.html)一致,但过程将会十分简便。 - -本章节以一个多层感知器为例,介绍了使用SciAI训练并求解如下方程。 - -$$ -f(x) = {x_1}^2 + sin(x_2) -$$ - -该部分完整代码请参考[代码](https://gitee.com/mindspore/mindscience/blob/master/SciAI/tutorial/example_net.py)。 - -### 模型搭建 - -如下示例代码创建了一个输入维度为2,输出维度为1,包含两层维度为5的中间层的多层感知器。 - -```python -from sciai.architecture import MLP -from sciai.common.initializer import XavierTruncNormal - -net = MLP(layers=[2, 5, 5, 1], weight_init=XavierTruncNormal(), bias_init='zeros', activation="tanh") -``` - -`MLP`将默认使用正态分布随机生成网络权重,偏差`bias`默认为0,激活函数默认为`tanh`。 - -`MLP`同时接受多样化的初始化方式和MindSpore提供的所有[激活函数](https://www.mindspore.cn/docs/zh-CN/master/api_python/mindspore.nn.html),以及专为科学计算设计的激活函数。 - -### 损失函数定义 - -损失函数定义为[Cell](https://www.mindspore.cn/docs/zh-CN/master/api_python/nn/mindspore.nn.Cell.html#mindspore.nn.Cell)的子类,并将损失的计算方法写在方法`construct`中。 - -```python -from mindspore import nn -from sciai.architecture import MSE - -class ExampleLoss(nn.Cell): - def __init__(self, network): - super().__init__() - self.network = network - self.mse = MSE() - - def construct(self, x, y_true): - y_predict = self.network(x) - return self.mse(y_predict - y_true) - -net_loss = ExampleLoss(net) -``` - -此时,通过直接调用`net_loss`,并将输入`x`与真实值`y_true`作为参数,便可计算得到当前`net`预测的损失。 - -```python -from mindspore import Tensor - -x = Tensor([[0.5, 0.5]]) -y_true = Tensor([0.72942554]) -print("loss value: ", net_loss(x, y_true)) -# expected output -... -loss value: 0.3026065 -``` - -### 模型训练与推理 - -得到损失函数后,我们即可使用SciAI框架中已封装好的训练类,使用数据集进行训练。 -在本案例中,我们对方程进行随机采样,生成数据集`x_train`与`y_true`进行训练。 - -模型训练部分代码如下所示,其中主要展示了SciAI若干功能。 -模型训练类`TrainCellWithCallBack`,其与[MindSpore.nn.TrainOneStepCell](https://www.mindspore.cn/docs/zh-CN/master/api_python/nn/mindspore.nn.TrainOneStepCell.html#mindspore.nn.TrainOneStepCell)功能基本一致, -需要提供网络`net_loss`与优化器作为参数,并为科学计算功能增加了回调功能。 -回调包括打印训练`loss`值、训练时间、自动保存`ckpt`文件。 -如下的案例代码将会每100个训练周期打印`loss`值与训练时间,并在每1000个训练周期保存当前模型参数为`ckpt`文件。 -SciAI提供`to_tensor`工具,可以方便地将多个`numpy`数据同时转换为`Tensor`类型。 -使用`log_config`指定目标目录,用于自动保存`TrainCellWithCallBack`的回调打印,以及用户使用`print_log`所打印的内容。 - -```python -import numpy as np -from mindspore import nn -from sciai.common import TrainCellWithCallBack -from sciai.context import init_project -from sciai.utils import to_tensor, print_log, log_config - -# Get the correct platform automatically and set to GRAPH_MODE by default. -init_project() -# Auto log saving -log_config("./logs") - -def func(x): - """The function to be learned to""" - return x[:, 0:1] ** 2 + np.sin(x[:, 1:2]) - -optimizer = nn.Adam(net_loss.trainable_params()) -trainer = TrainCellWithCallBack(net_loss, optimizer, loss_interval=100, time_interval=100, ckpt_interval=1000) -x_train = np.random.rand(1000, 2) -# Randomly collect ground truth -y_true = func(x_train) -# Convert to Tensor data type -x_train, y_true = to_tensor((x_train, y_true)) -for _ in range(10001): - trainer(x_train, y_true) -print_log("Finished") -``` - -预期运行结果如下。 - -```bash -python ./example_net.py -# expected output -... -step: 0, loss: 0.5189553, interval: 2.7039313316345215s, total: 2.7039313316345215s -step: 100, loss: 0.080132075, interval: 0.11984062194824219s, total: 2.8237719535827637s -step: 200, loss: 0.055663396, interval: 0.09104156494140625s, total: 2.91481351852417s -step: 300, loss: 0.032194577, interval: 0.09095025062561035s, total: 3.0057637691497803s -step: 400, loss: 0.015914217, interval: 0.09099435806274414s, total: 3.0967581272125244s -... -Finished -``` - -在训练结束并且损失收敛时,通过调用`y = net(x)`即可得到`x`处的预测值`y`。 -继续随机采样若干位置`x_val`用于验证。 - -```python -x_val = np.random.rand(5, 2) -y_true = func(x_val) -y_pred = net(to_tensor(x_val)).asnumpy() -print_log("y_true:") -print_log(y_true) -print_log("y_pred:") -print_log(y_pred) -``` - -预期运行结果如下。经过训练,模型的预测值接近数值计算结果。 - -```bash -# expected output -y_true: -[[0.34606973] - [0.70457536] - [0.90531053] - [0.84420218] - [0.48239506]] -y_pred: -[[0.34271246] - [0.70356864] - [0.89893466] - [0.8393946 ] - [0.47805673]] -``` - -## 模型构建拓展 - -使用SciAI可以求解更为复杂的问题,例如物理驱动的神经网络(PINN)。该章节继续以一个多层感知器为例,介绍使用SciAI训练并求解如下偏微分方程。 - -$$ -\frac{\partial{f}}{\partial{x}} - 2 \frac{f}{x} + {x}^2 {y}^2 = 0 -$$ - -边界条件定义如下。 - -$$ -f(0) = 0, f(1) = 1 -$$ - -在此边界条件下,函数的解析解为: - -$$ -f(x) = \frac{x^2}{0.2 x^5 + 0.8} -$$ - -该部分完整代码请参考[代码](https://gitee.com/mindspore/mindscience/blob/master/SciAI/tutorial/example_grad_net.py)。 - -### 损失函数定义 - -与上一章中损失函数定义基本一致,需要定义损失为[Cell](https://www.mindspore.cn/docs/zh-CN/master/api_python/nn/mindspore.nn.Cell.html#mindspore.nn.Cell)的子类。 - -不同的是在该损失函数中,需要计算原函数的偏导。 -SciAI为此提供了便捷的工具`operators.grad`,通过设置网络输入与输出的索引,可以计算某个输入对某个输出的偏导值。 -在该问题中,输入输出维度均为1,因此设置`input_index`与`output_index`为0。 - -```python -from mindspore import nn, ops -from sciai.architecture import MSE, MLP -from sciai.operators import grad - -class ExampleLoss(nn.Cell): - """ Loss definition class""" - def __init__(self, network): - super().__init__() - self.network = network - self.dy_dx = grad(net=self.network, output_index=0, input_index=0) # partial differential definition - self.mse = MSE() - - def construct(self, x, x_bc, y_bc_true): - y = self.network(x) - dy_dx = self.dy_dx(x) - domain_res = dy_dx - 2 * ops.div(y, x) + ops.mul(ops.pow(x, 2), ops.pow(y, 2)) # PDE residual error - - y_bc = self.network(x_bc) - bc_res = y_bc_true - y_bc # Boundary conditions residual - return self.mse(domain_res) + 10 * self.mse(bc_res) -``` - -### 模型训练与推理 - -通过终端执行脚本文件,执行训练与推理,得到如下预期结果。最终预测值`y_pred`与真实值`y_true`基本接近。 - -```bash -python ./example_grad_net.py -# expected output -... -step: 0, loss: 3.1961572, interval: 3.117840051651001s, total: 3.117840051651001s -step: 100, loss: 1.0862937, interval: 0.23533344268798828s, total: 3.353173494338989s -step: 200, loss: 0.7334847, interval: 0.21307134628295898s, total: 3.566244840621948s -step: 300, loss: 0.5629723, interval: 0.19696831703186035s, total: 3.763213157653809s -step: 400, loss: 0.4133342, interval: 0.20153212547302246s, total: 3.964745283126831s -... -Finished -y_true: -[[0.02245186] - [0.99459697] - [0.04027248] - [0.12594332] - [0.39779923]] -y_pred: -[[0.02293926] - [0.99337316] - [0.03924912] - [0.12166673] - [0.4006738 ]] -``` \ No newline at end of file diff --git a/docs/sciai/docs/source_zh_cn/conf.py b/docs/sciai/docs/source_zh_cn/conf.py deleted file mode 100644 index bf84e1ca21..0000000000 --- a/docs/sciai/docs/source_zh_cn/conf.py +++ /dev/null @@ -1,315 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import glob -import os -import shutil -import IPython -import re -import sys -import sphinx -import sphinx.ext.autosummary.generate as g -sys.path.append(os.path.abspath('../_ext')) - -from sphinx import directives -with open('../_ext/overwriteobjectiondirective.txt', 'r') as f: - exec(f.read(), directives.__dict__) - -from sphinx.ext import viewcode -with open('../_ext/overwriteviewcode.txt', 'r', encoding="utf8") as f: - exec(f.read(), viewcode.__dict__) - -from sphinx.ext import autodoc as sphinx_autodoc - -# -- Project information ----------------------------------------------------- - -project = 'MindSpore SciAI' -copyright = 'MindSpore' -author = 'MindSpore' - -# The full version, including alpha/beta/rc tags -release = 'master' - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -myst_enable_extensions = ["dollarmath", "amsmath"] - - -myst_heading_anchors = 5 -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.doctest', - 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', - 'sphinx.ext.napoleon', - 'sphinx.ext.viewcode', - 'myst_parser', - 'sphinx.ext.mathjax', - 'IPython.sphinxext.ipython_console_highlighting' -] - -source_suffix = { - '.rst': 'restructuredtext', - '.md': 'markdown', -} - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -mathjax_path = 'https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/mathjax/MathJax-3.2.2/es5/tex-mml-chtml.js' - -mathjax_options = { - 'async':'async' -} - -smartquotes_action = 'De' - -exclude_patterns = [] - -pygments_style = 'sphinx' - -autodoc_inherit_docstrings = False - -autosummary_generate = True - -autosummary_generate_overwrite = False - -# -- Options for HTML output ------------------------------------------------- - -# Reconstruction of sphinx auto generated document translation. -language = 'zh_CN' -locale_dirs = ['../../../../resource/locale/'] -gettext_compact = False - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'sphinx_rtd_theme' - -html_search_language = 'zh' - -html_search_options = {'dict': '../../../resource/jieba.txt'} - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - 'python': ('https://docs.python.org/3', '../../../../resource/python_objects.inv'), -} - -# Modify regex for sphinx.ext.autosummary.generate.find_autosummary_in_lines. -gfile_abs_path = os.path.abspath(g.__file__) -autosummary_re_line_old = r"autosummary_re = re.compile(r'^(\s*)\.\.\s+autosummary::\s*')" -autosummary_re_line_new = r"autosummary_re = re.compile(r'^(\s*)\.\.\s+(ms[a-z]*)?autosummary::\s*')" -with open(gfile_abs_path, "r+", encoding="utf8") as f: - data = f.read() - data = data.replace(autosummary_re_line_old, autosummary_re_line_new) - exec(data, g.__dict__) - -sys.path.append(os.path.abspath('../../../../resource/sphinx_ext')) -# import nbsphinx_mod - -# Modify default signatures for autodoc. -autodoc_source_path = os.path.abspath(sphinx_autodoc.__file__) -autodoc_source_re = re.compile(r'stringify_signature\(.*?\)') -get_param_func_str = r"""\ -import re -import inspect as inspect_ - -def remove_typehints_content(text): - # 初始化括号匹配标记,0为无括号包裹 - bracket_count = 0 - start_idx = -1 # 记录第一个":"的位置 - - for i, char in enumerate(text): - # 1. 找到第一个":",记录起始位置 - if start_idx == -1 and char == ":": - start_idx = i - continue - - # 2. 已找到":",开始判断括号状态 - if start_idx != -1: - # 遇到"("或"[",括号计数+1(进入括号内) - if char in ("(", "["): - bracket_count += 1 - # 遇到")"或"]",括号计数-1(离开括号内) - elif char in (")", "]"): - bracket_count = max(0, bracket_count - 1) # 避免负数值 - # 3. 找到不在括号内的第一个",",执行删除 - elif char == "," and bracket_count == 0: - return text[:start_idx] + text[i:] # 拼接删除后的内容 - # 4. 找到不在括号内的第一个"=",执行删除 - elif char == "=" and bracket_count == 0: - return text[:start_idx] + " " + text[i:] # 拼接删除后的内容,"="前需要有一个空格 - - # 若未找到目标",",返回原文本 - return text - -def get_param_func(func): - try: - source_code = inspect_.getsource(func) - if func.__doc__: - source_code = source_code.replace(func.__doc__, '') - all_params_str = re.findall(r"def [\w_\d\-]+\(([\S\s]*?)(\):|\) ->.*?:)", source_code) - all_params = re.sub("(self|cls)(,|, )?", '', all_params_str[0][0].replace("\n", "").replace("'", "\"")) - - if ":" in all_params: - colon_idx = all_params.find(":") - # 处理非最后一个":"以后的内容 - while colon_idx != -1 and "," in all_params[colon_idx+1:]: - all_params = remove_typehints_content(all_params) - # 最后一个":"以后的内容中包含"," - if colon_idx == all_params.find(":"): - break - colon_idx = all_params.find(":") - - # 去掉最后一个":"以后的内容 - colon_idx = all_params.find(":") - if colon_idx != -1: - # 最后一个":"以后的内容中包含"=",需要保留"="及以后的内容 - if "=" in all_params[colon_idx+1:]: - all_params = re.sub(":(.*?)=", ' =', all_params) - # 正常删除最后一个":"以后的内容 - else: - all_params = re.sub(":.*$", '', all_params) - # 目前仅有lambda x出现在最后的情况 - if all_params.endswith("lambda x"): - all_params += ": ..." - - return all_params - except: - return '' - -def get_obj(obj): - if isinstance(obj, type): - return obj.__init__ - - return obj -""" - -with open(autodoc_source_path, "r+", encoding="utf8") as f: - code_str = f.read() - code_str = autodoc_source_re.sub('"(" + get_param_func(get_obj(self.object)) + ")"', code_str, count=0) - exec(get_param_func_str, sphinx_autodoc.__dict__) - exec(code_str, sphinx_autodoc.__dict__) - -sys.path.append(os.path.abspath('../../../../resource/search')) -import search_code - -sys.path.append(os.path.abspath('../../../../resource/custom_directives')) -from custom_directives import IncludeCodeDirective - -# Copy source files of chinese python api from sciai repository. -import shutil -from sphinx.util import logging -logger = logging.getLogger(__name__) - -copy_path = 'docs/api_python/sciai' -src_dir = os.path.join(os.getenv("MSC_PATH"), copy_path) - -copy_list = [] - -present_path = os.path.dirname(__file__) - -for i in os.listdir(src_dir): - if os.path.isfile(os.path.join(src_dir,i)): - if os.path.exists('./'+i): - os.remove('./'+i) - shutil.copy(os.path.join(src_dir,i),'./'+i) - copy_list.append(os.path.join(present_path,i)) - else: - if os.path.exists('./'+i): - shutil.rmtree('./'+i) - shutil.copytree(os.path.join(src_dir,i),'./'+i) - copy_list.append(os.path.join(present_path,i)) - -# add view -import json - -if os.path.exists('../../../../tools/generate_html/version.json'): - with open('../../../../tools/generate_html/version.json', 'r+', encoding='utf-8') as f: - version_inf = json.load(f) -elif os.path.exists('../../../../tools/generate_html/daily_dev.json'): - with open('../../../../tools/generate_html/daily_dev.json', 'r+', encoding='utf-8') as f: - version_inf = json.load(f) -elif os.path.exists('../../../../tools/generate_html/daily.json'): - with open('../../../../tools/generate_html/daily.json', 'r+', encoding='utf-8') as f: - version_inf = json.load(f) - -if os.getenv("MSC_PATH").split('/')[-1]: - copy_repo = os.getenv("MSC_PATH").split('/')[-1] -else: - copy_repo = os.getenv("MSC_PATH").split('/')[-2] - -branch = [version_inf[i]['branch'] for i in range(len(version_inf)) if version_inf[i]['name'] == copy_repo][0] -docs_branch = [version_inf[i]['branch'] for i in range(len(version_inf)) if version_inf[i]['name'] == 'tutorials'][0] - -re_view = f"\n.. image:: https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/{docs_branch}/" + \ - f"resource/_static/logo_source.svg\n :target: https://gitee.com/mindspore/{copy_repo}/blob/{branch}/" - -for cur, _, files in os.walk(present_path): - for i in files: - flag_copy = 0 - if i.endswith('.rst'): - for j in copy_list: - if j in cur: - flag_copy = 1 - break - if os.path.join(cur, i) in copy_list or flag_copy: - try: - with open(os.path.join(cur, i), 'r+', encoding='utf-8') as f: - content = f.read() - new_content = content - if '.. include::' in content and '.. automodule::' in content: - continue - if 'autosummary::' not in content and "\n=====" in content: - re_view_ = re_view + copy_path + cur.split(present_path)[-1] + '/' + i + \ - '\n :alt: 查看源文件\n\n' - new_content = re.sub('([=]{5,})\n', r'\1\n' + re_view_, content, 1) - if new_content != content: - f.seek(0) - f.truncate() - f.write(new_content) - except Exception: - print(f'打开{i}文件失败') - -import sciai -from myautosummary import MsPlatformAutoSummary, MsCnPlatformAutoSummary, MsCnAutoSummary - -rst_files = set([i.replace('.rst', '') for i in glob.glob('./**/*.rst', recursive=True)]) - -def setup(app): - app.add_directive('msplatformautosummary', MsPlatformAutoSummary) - app.add_directive('mscnplatformautosummary', MsCnPlatformAutoSummary) - app.add_directive('mscnautosummary', MsCnAutoSummary) - app.add_directive('includecode', IncludeCodeDirective) - app.add_config_value('rst_files', set(), False) - -src_release = os.path.join(os.getenv("MSC_PATH"), 'SciAI/RELEASE_CN.md') -des_release = "./RELEASE.md" -with open(src_release, "r", encoding="utf-8") as f: - data = f.read() -if len(re.findall("\n## (.*?)\n",data)) > 1: - content = re.findall("(## [\s\S\n]*?)\n## ", data) -else: - content = re.findall("(## [\s\S\n]*)", data) -#result = content[0].replace('# MindFlow', '#', 1) -with open(des_release, "w", encoding="utf-8") as p: - p.write("# Release Notes"+"\n\n") - p.write(content[0]) \ No newline at end of file diff --git a/docs/sciai/docs/source_zh_cn/images/architecture_cn.png b/docs/sciai/docs/source_zh_cn/images/architecture_cn.png deleted file mode 100644 index 10e3de7876b700697de1b80943caabe9773cd896..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52511 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

    9oGTb)T6LEkddn}>;TUM!SM2(Gh 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�Ly~yEN5>5@w}y(2Fnm2Lest$* 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 H{_g((;rw;9 diff --git a/docs/sciai/docs/source_zh_cn/index.rst b/docs/sciai/docs/source_zh_cn/index.rst deleted file mode 100644 index 6ae8935ee0..0000000000 --- a/docs/sciai/docs/source_zh_cn/index.rst +++ /dev/null @@ -1,52 +0,0 @@ -MindSpore SciAI介绍 -=================== - -MindSpore SciAI是基于昇思MindSpore打造的AI4SCI高频基础模型套件,内置了60+高频模型,覆盖物理感知(如PINNs、DeepRitz以及PFNN)和神经算子(如FNO、DeepONet、PDENet)等主流模型,覆盖度全球第一; -提供了高阶API(一键环境配置,自动模型加载、极简训练微调等),开发者和用户开箱即用。 -MindSpore SciAI应用领域覆盖到了流体、电磁、声、热、固体、生物等众多学科,为广大开发者和用户提供了高效、易用的AI4Science通用计算平台。 - -.. raw:: html - - - -.. toctree:: - :maxdepth: 1 - :caption: 安装部署 - - installation - -.. toctree:: - :maxdepth: 1 - :caption: 启动指南 - - launch_with_scripts - launch_with_api - -.. toctree:: - :maxdepth: 1 - :caption: 模型列表 - - model_library - -.. toctree:: - :maxdepth: 1 - :caption: 教学示例 - - build_model_with_sciai - -.. toctree:: - :maxdepth: 1 - :caption: API参考 - - sciai.architecture - sciai.common - sciai.context - sciai.operators - sciai.utils - -.. toctree:: - :glob: - :maxdepth: 1 - :caption: RELEASE NOTES - - RELEASE diff --git a/docs/sciai/docs/source_zh_cn/installation.md b/docs/sciai/docs/source_zh_cn/installation.md deleted file mode 100644 index 46e76ba6ed..0000000000 --- a/docs/sciai/docs/source_zh_cn/installation.md +++ /dev/null @@ -1,66 +0,0 @@ -# MindSpore SciAI安装 - -[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/sciai/docs/source_zh_cn/installation.md) -   - -## 确认系统环境信息 - -- 硬件平台为Ascend或GPU。 -- 参考[MindSpore安装指南](https://www.mindspore.cn/install),完成MindSpore的安装。 -- 其余依赖请参见[requirements.txt](https://gitee.com/mindspore/mindscience/blob/master/SciAI/requirements.txt)。 - -## 安装方式 - -可以采用pip安装或者源码编译安装两种方式。 - -### 方式一:pip安装 - -此方式不用克隆源码编译,而是自动下载安装MindSpore官方提供的whl包。 - -```bash -pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.2.0/MindScience/sciai/gpu/{arch}/cuda-11.1/sciai-{version}-cp37-cp37m-linux_{arch}.whl -i https://pypi.tuna.tsinghua.edu.cn/simple -``` - -> - 在联网状态下,安装whl包时会自动下载SciAI安装包的依赖项(依赖项详情参见setup.py)。 -> - {version}表示SciAI版本号,例如下载0.1.0版本SciAI时,{version}应写为`0.1.0`。 -> - {arch}表示系统架构,例如使用的Linux系统是x86架构64位时,{arch}应写为`x86_64`。如果系统是ARM架构64位,则写为`aarch64`。 - -下表提供了各架构和Python版本对应的安装命令。 - -| 设备 | 架构 | Python | 安装命令 | -|--------|---------|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Ascend | x86_64 | Python=3.7 | `pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.2.0/MindScience/sciai/gpu/x86_64/cuda-11.1/sciai-0.1.0-cp37-cp37m-linux_x86_64.whl -i https://pypi.tuna.tsinghua.edu.cn/simple` | -| | aarch64 | Python=3.7 | `pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.2.0/MindScience/sciai/ascend/aarch64/sciai-0.1.0-cp37-cp37m-linux_aarch64.whl -i https://pypi.tuna.tsinghua.edu.cn/simple` | -| GPU | x86_64 | Python=3.7 | `pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.2.0/MindScience/sciai/gpu/x86_64/cuda-11.1/sciai-0.1.0-cp37-cp37m-linux_x86_64.whl -i https://pypi.tuna.tsinghua.edu.cn/simple` | - -注意:如果您的conda或python env中已经安装了其他MindScience套件,如`MindElec`,`MindFlow`,`MindSponge`,请先卸载环境中的MindScience套件避免pip行为冲突。 - -### 方式二:源码安装 - -1. 克隆MindScience代码Git仓库。 - - ```bash - cd ~ - git clone https://gitee.com/mindspore/mindscience.git - ``` - -2. 使用脚本`build.sh`编译SciAI。 - - ```bash - cd mindscience/SciAI - bash build.sh -j8 - ``` - -3. 编译完成后,通过如下命令安装编译所得`.whl`包。 - - ```bash - bash install.sh - ``` - -### 验证安装 - -执行如下命令,如果没有报错`No module named 'sciai'`,则说明安装成功。 - -```bash -python -c 'import sciai' -``` diff --git a/docs/sciai/docs/source_zh_cn/launch_with_api.md b/docs/sciai/docs/source_zh_cn/launch_with_api.md deleted file mode 100644 index ebb42da086..0000000000 --- a/docs/sciai/docs/source_zh_cn/launch_with_api.md +++ /dev/null @@ -1,56 +0,0 @@ -# 调用API启动模型 - -[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/sciai/docs/source_zh_cn/launch_with_api.md)   - -MindSpore SciAI为用户提供了高阶API接口`AutoModel`。借助`AutoModel`,用户可以通过一行代码完成模型的实例化。 - -用户可以通过`AutoModel`的接口进行模型参数更新,并启动训练或评估。 - -## 使用AutoModel获取模型 - -用户可以使用`AutoModel.from_pretrained`接口获取已支持的网络模型。 - -这里使用Conservatice Physics-Informed Neural Networks (CPINNs) 作为教学案例。CPINNs模型相关代码请参考[链接](https://gitee.com/mindspore/mindscience/tree/master/SciAI/sciai/model/cpinns)。 - -更多关于该模型的信息,请参考[论文](https://www.sciencedirect.com/science/article/abs/pii/S0045782520302127)。 - -```python -from sciai.model import AutoModel - -# 获取cpinns网络模型 -model = AutoModel.from_pretrained("cpinns") -``` - -## 使用AutoModel训练、微调模型 - -用户可以使用`AutoModel.train`实现模型的训练,并且在执行训练之前, -使用`AutoModel.update_config`调整训练参数,或是加载`.ckpt`文件实现模型微调。 -接口`AutoModel.update_config`所接受的可选参数依赖于模型类型。 - -```python -from sciai.model import AutoModel - -# 获取cpinns网络模型 -model = AutoModel.from_pretrained("cpinns") -# (可选)加载参数ckpt文件,使用已有参数进行模型初始化 -model.update_config(load_ckpt=True, load_ckpt_path="./checkpoints/your_file.ckpt", epochs=500) -# 使用默认参数训练网络,生成的图片、数据与日志将保存至用户的执行目录中 -model.train() -``` - -## 使用AutoModel评估模型 - -用户可以使用`AutoModel.evaluate`评估训练结果。 - -该接口将默认加载SciAI模型库中提供的`.ckpt`文件用于评估,用户也可以调用`model.update_config`接口自定义加载的文件。 - -```python -from sciai.model import AutoModel - -# 获取cpinns网络模型 -model = AutoModel.from_pretrained("cpinns") -# (可选)自定义加载ckpt文件 -model.update_config(load_ckpt=True, load_ckpt_path="./checkpoints/your_file.ckpt") -# 评估网络模型 -model.evaluate() -``` diff --git a/docs/sciai/docs/source_zh_cn/launch_with_scripts.md b/docs/sciai/docs/source_zh_cn/launch_with_scripts.md deleted file mode 100644 index 18e1469051..0000000000 --- a/docs/sciai/docs/source_zh_cn/launch_with_scripts.md +++ /dev/null @@ -1,64 +0,0 @@ -# 脚本启动模型 - -[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/sciai/docs/source_zh_cn/launch_with_scripts.md)   - -MindSpore SciAI中的模型为用户提供了训练与评估的脚本文件。 - -通过模型的脚本文件,用户可以直接启动某个模型的训练与评估,并通过修改配置文件或是传入命令行参数的方式调整模型参数。[该目录](https://gitee.com/mindspore/mindscience/tree/master/SciAI/sciai/model)中包含了所有支持脚本启动的模型。 - -下面使用模型Conservative Physics-Informed Neural Networks(CPINNs)介绍使用脚本训练、评估模型的基本通用流程。CPINNs模型相关代码请参考[链接](https://gitee.com/mindspore/mindscience/tree/master/SciAI/sciai/model/cpinns)。 - -更多关于该模型的信息,请参考[论文](https://www.sciencedirect.com/science/article/abs/pii/S0045782520302127)。 - -## 仓库下载 - -使用如下命令直接克隆整个仓库,并初始化环境变量`PYTHONPATH`。 - -```bash -git clone https://gitee.com/mindspore/mindscience -source ./mindscience/SciAI/.env -``` - -克隆完成后,用户可以按照模型[README_CN.md](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/cpinns/README_CN.md)(以模型CPINNs为例)中的`快速开始`章节,使用脚本进行训练与推理。 - -```bash -cd ./mindscience/SciAI/sciai/model/cpinns/ -``` - -## 训练、微调模型 - -用户可以使用训练脚本[train.py](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/cpinns/train.py)进行网络模型训练。 - -```bash -python ./train.py [--parameters] -# expected output -... -step: 0, loss1: 2.1404986, loss2: 8.205103, loss3: 37.23588, loss4: 3.56359, interval: 50.85803508758545s, total: 50.85803508758545s -step: 10, loss1: 2.6560388, loss2: 3.869413, loss3: 9.323585, loss4: 2.1194165, interval: 5.159524917602539s, total: 56.01756000518799s -step: 20, loss1: 1.7885156, loss2: 4.470225, loss3: 3.3072894, loss4: 1.5674783, interval: 1.8615927696228027s, total: 57.87915277481079s -... -``` - -使用已有的`.ckpt`文件进行模型微调。 - -```bash -python ./train.py --load_ckpt true --load_ckpt_path {your_file}.ckpt [--parameters] -``` - -使用可选参数`[--parameters]`可以配置模型的训练过程,包括学习率、训练周期、数据读取保存路径等。 - -具体可配置的参数列表请参考[README_CN.md](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/cpinns/README_CN.md)中`脚本参数`章节。 - -## 评估模型 - -用户可以使用脚本`eval.py`对已完成训练的网络模型进行评估。 - -```bash -python ./eval.py [--parameters] -# expected output -... -error_u: 0.024803562642018585 -Total time running eval: 20.625872135162354 seconds -``` - -使用可选参数`[--parameters]`可以配置模型的评估过程,包括数据读取保存路径、checkpoints文件加载路径等。 diff --git a/docs/sciai/docs/source_zh_cn/model_library.md b/docs/sciai/docs/source_zh_cn/model_library.md deleted file mode 100644 index cb5f53052c..0000000000 --- a/docs/sciai/docs/source_zh_cn/model_library.md +++ /dev/null @@ -1,72 +0,0 @@ -# 网络模型库 - -[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/sciai/docs/source_zh_cn/model_library.md)   - -SciAI基础模型库提供了丰富的科学计算高频模型,下表中汇总了当前已实现的网络模型及其对应领域。 - -| 领域 | 模型 | MindSpore实现与网络参数 | Ascend | GPU | -|-------|--------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------:|:---:| -| 通用物理 | [auq_pinns](https://www.sciencedirect.com/science/article/pii/S0021999119303584) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/auq_pinns/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [cpinns](https://www.sciencedirect.com/science/article/abs/pii/S0045782520302127) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/cpinns/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [deep_hpms](https://www.jmlr.org/papers/volume19/18-046/18-046.pdf) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/deep_hpms/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [deep_ritz](https://arxiv.org/abs/1710.00211) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/deep_ritz/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [deepbsde](https://www.pnas.org/doi/10.1073/pnas.1718942115) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/deepbsde/README.md#script-parameters) | | ✅ | -| 通用物理 | [deeponet](https://www.nature.com/articles/s42256-021-00302-5) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/deeponet/README_CN.md#脚本参数) | | ✅ | -| 通用物理 | [dgm](https://arxiv.org/abs/1708.07469) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/dgm/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [fbsnns](https://arxiv.org/abs/1804.07010) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/fbsnns/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [fpinns](https://arxiv.org/abs/1811.08967) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/fpinns/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [gradient_pathologies_pinns](https://arxiv.org/abs/2001.04536) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/gradient_pathologies_pinns/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [hp_vpinns](https://arxiv.org/abs/2003.05385) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/hp_vpinns/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [laaf](https://doi.org/10.1016/j.jcp.2019.109136) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/laaf/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [mgnet](https://link.springer.com/article/10.1007/s11425-019-9547-2) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/mgnet/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [multiscale_pinns](https://www.sciencedirect.com/science/article/abs/pii/S0045782521002759) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/multiscale_pinns/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [pfnn](https://www.sciencedirect.com/science/article/abs/pii/S0021999120308597) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pfnn/README_CN.md#脚本说明) | | ✅ | -| 通用物理 | [phygeonet](https://www.sciencedirect.com/science/article/abs/pii/S0021999120308536) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/phygeonet/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [pi_deeponet](https://www.sciencedirect.com/science/article/abs/pii/S0021999122009184) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pi_deeponet/README_CN.md#脚本参数) | | ✅ | -| 通用物理 | [pinns](https://www.sciencedirect.com/science/article/abs/pii/S0021999118307125) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinns/README_CN.md#脚本参数) | | ✅ | -| 通用物理 | [pinns_ntk](https://www.sciencedirect.com/science/article/pii/S002199912100663X) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinns_ntk/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [ppinns](https://www.sciencedirect.com/science/article/abs/pii/S0045782520304357) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/ppinns/README_CN.md#脚本参数) | ✅ | ✅ | -| 通用物理 | [xpinns](https://doi.org/10.4208/cicp.OA-2020-0164) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/xpinns/README_CN.md#脚本参数) | ✅ | ✅ | -| 哈密顿系统 | [sympnets](https://www.sciencedirect.com/science/article/pii/S0893608020303063) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/sympnets/README_CN.md#脚本参数) | ✅ | ✅ | -| 流体力学 | [hfm](https://www.science.org/doi/abs/10.1126/science.aaw4741) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/hfm/README_CN.md#脚本参数) | ✅ | ✅ | -| 流体力学 | [label_free_dnn_surrogate](https://www.sciencedirect.com/science/article/pii/S004578251930622X) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/label_free_dnn_surrogate/README_CN.md#脚本参数) | ✅ | ✅ | -| 流体力学 | [nsf_nets](https://www.sciencedirect.com/science/article/pii/S0021999120307257) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/nsf_nets/README_CN.md#脚本参数) | ✅ | ✅ | -| 流体力学 | [*burgers_fno](https://arxiv.org/abs/2010.08895) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_driven/burgers/fno1d/FNO1D_CN.ipynb) | ✅ | ✅ | -| 流体力学 | [*burgers_kno](https://arxiv.org/abs/2301.10022) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_driven/burgers/kno1d/KNO1D_CN.ipynb) | ✅ | ✅ | -| 流体力学 | [*navier_stokes_fno](https://arxiv.org/abs/2010.08895) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_driven/navier_stokes/fno2d/FNO2D_CN.ipynb) | ✅ | ✅ | -| 流体力学 | [*navier_stokes_kno](https://arxiv.org/abs/2301.10022) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_driven/navier_stokes/kno2d/KNO2D_CN.ipynb) | ✅ | ✅ | -| 流体力学 | [*navier_stokes_3d_fno](https://arxiv.org/abs/2010.08895) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_driven/navier_stokes/fno3d/FNO3D_CN.ipynb) | ✅ | ✅ | -| 流体力学 | [*pde_net](https://arxiv.org/abs/1710.09668) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_mechanism_fusion/pde_net/README_CN.md) | ✅ | ✅ | -| 流体力学 | [*percnn](https://www.nature.com/articles/s42256-023-00685-7) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/data_mechanism_fusion/percnn/README_CN.md) | ✅ | ✅ | -| 弹性动力学 | [pinn_elastodynamics](https://arxiv.org/abs/2006.08472) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinn_elastodynamics/README_CN.md#脚本参数) | ✅ | ✅ | -| 热力学 | [pinn_heattransfer](https://arxiv.org/abs/1711.10561) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinn_heattransfer/README_CN.md#脚本参数) | ✅ | ✅ | -| 气象学 | [enso](https://doi.org/10.1038/s41586-019-1559-7) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/enso/README_CN.md#脚本参数) | ✅ | ✅ | -| 地质学 | [inversion_net](https://ieeexplore.ieee.org/abstract/document/8918045/) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/inversion_net/README_CN.md#脚本参数) | ✅ | ✅ | -| 地质学 | [pinn_helmholtz](https://academic.oup.com/gji/article-abstract/228/3/1750/6409132) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinn_helmholtz/README_CN.md#脚本参数) | ✅ | ✅ | -| 海洋物理 | [ocean_model](https://gmd.copernicus.org/articles/12/4729/2019/) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/ocean_model/README_CN.md#模型说明) | | ✅ | -| 海洋物理 | [pinns_swe](https://arxiv.org/abs/2104.00615) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/pinns_swe/README_CN.md#脚本参数) | ✅ | ✅ | -| 电磁学 | [maxwell_net](https://arxiv.org/abs/2107.06164) | [link](https://gitee.com/mindspore/mindscience/blob/master/SciAI/sciai/model/maxwell_net/README_CN.md#脚本参数) | ✅ | ✅ | -| 电磁学 | [*AD_FDTD_invert_f](https://www.mindspore.cn/mindelec/docs/zh-CN/r0.2/AD_FDTD.html) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/AD_FDTD/fdtd_forward/README_CN.md#脚本参数) | | ✅ | -| 电磁学 | [*AD_FDTD_microstrip_filter](https://www.mindspore.cn/mindelec/docs/zh-CN/r0.2/AD_FDTD.html) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/AD_FDTD/fdtd_forward/README_CN.md#脚本参数) | | ✅ | -| 电磁学 | [*AD_FDTD_inverse](https://www.mindspore.cn/mindelec/docs/zh-CN/r0.2/AD_FDTD.html) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/AD_FDTD/fdtd_inverse/README_CN.md#脚本参数) | | ✅ | -| 电磁学 | [*frequency_domain_maxwell](https://arxiv.org/abs/2107.06164) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/frequency_domain_maxwell/README_CN.md#脚本参数) | ✅ | ✅ | -| 电磁学 | [*frequency_domain_maxwell_3D_dielectric_slab](https://arxiv.org/abs/2107.06164) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/frequency_domain_maxwell_3D/dielectric_slab_3d/README.md#脚本参数) | ✅ | ✅ | -| 电磁学 | [*frequency_domain_maxwell_3D_waveguide_cavity](https://arxiv.org/abs/2107.06164) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/frequency_domain_maxwell_3D/waveguide_cavity_3d/README.md#脚本参数) | ✅ | ✅ | -| 电磁学 | [*meta_auto_decoder](https://arxiv.org/abs/2111.08823) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/incremental_learning/README_CN.md#脚本参数) | ✅ | ✅ | -| 电磁学 | [*pinn_fwi](https://agupubs.onlinelibrary.wiley.com/doi/abs/10.1029/2021JB023120) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/pinn_fwi/README.md#脚本参数) | ✅ | ✅ | -| 电磁学 | [*SED_ANN](https://gitee.com/mindspore/mindscience/tree/master/MindElec/examples/data_driven/sed_ann) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/data_driven/sed_ann/README_CN.md#脚本参数) | ✅ | ✅ | -| 电磁学 | [*time_domain_maxwell](https://www.ijcai.org/proceedings/2022/533) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/physics_driven/time_domain_maxwell/README_CN.md#脚本参数) | ✅ | ✅ | -| 电磁学 | [*metasurface_holograms](https://www.researching.cn/articles/OJ44d3746c3db8c1e1) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindElec/examples/metasurface/metasurface_holograms/README_CN.md#脚本参数) | ✅ | ✅ | -| 生物 | [*MEGA-Fold](https://arxiv.org/abs/2206.12240v1) | [link (推理)](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) [link (训练)](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) | ✅ | ✅ | -| 生物 | [*MEGA-EvoGen](https://arxiv.org/abs/2208.09652) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) | ✅ | ✅ | -| 生物 | [*MEGA-Assessment](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) | [link (推理)](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) [link (训练)](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/MEGAProtein.md) | ✅ | ✅ | -| 生物 | [*ColabDesign](https://www.biorxiv.org/content/10.1101/2021.11.10.468128.abstract) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/ColabDesign.md) | ✅ | ✅ | -| 生物 | [*DeepFRI](https://www.nature.com/articles/s41467-021-23303-9) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/DeepFri.md) | ✅ | ✅ | -| 生物 | [*Multimer](https://www.biorxiv.org/content/10.1101/2021.10.04.463034v1) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/afmultimer.md) | ✅ | ✅ | -| 生物 | [*ProteinMPNN](https://www.science.org/doi/abs/10.1126/science.add2187) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/ProteinMPNN.MD) | ✅ | ✅ | -| 生物 | [*UFold](https://doi.org/10.1093/nar/gkab1074) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/UFold.md) | ✅ | ✅ | -| 生物 | [*esm-if1](https://proceedings.mlr.press/v162/hsu22a.html) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/ESM-IF1.md) | ✅ | ✅ | -| 生物 | [*esm2](https://www.biorxiv.org/content/10.1101/2022.07.20.500902v1.full.pdf) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/ESM-2.md) | ✅ | ✅ | -| 生物 | [*grover](https://proceedings.neurips.cc/paper/2020/file/94aef38441efa3380a3bed3faf1f9d5d-Paper.pdf) | [link](https://gitee.com/mindspore/mindscience/blob/master/MindSPONGE/applications/model_cards/GROVER.MD) | ✅ | ✅ | - -注: 带有“*”的网络模型为MindSpore与MindScience先前已发布网络。 \ No newline at end of file -- Gitee