.. Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
   distributed with this work for additional information
   regarding copyright ownership.  The ASF licenses this file
   to you under the Apache License, Version 2.0 (the
   "License"); you may not use this file except in compliance
   with the License.  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing,
   software distributed under the License is distributed on an
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   KIND, either express or implied.  See the License for the
   specific language governing permissions and limitations
   under the License.

Welcome to Apache SINGA
=======================

Recent News
-----------

* SINGA was presented at `DISI, University of Trento, Italy <https://www.disi.unitn.it/>`_ on 14 December 2018.

* SINGA was presented at `DIBRIS, University of Genoa, Italy <https://www.dibris.unige.it/>`_ on 16 July 2018.

* **Version 1.2.0** is now available, 6 June, 2018. `Download SINGA v1.2.0 <downloads.html>`_

* **Version 1.1.0** is now available, 12 Feb, 2017. `Download SINGA v1.1.0 <downloads.html>`_

* A tutorial on SINGA V1 will be given at `SGInnovate <https://www.eventbrite.sg/e/ai-eveningssginnovate-apache-singa-tickets-31505061487>`_, on 23 March, 2017

* **Version 1.0.0** is now available, 9 Sep, 2016. `Download SINGA v1.0.0 <downloads.html>`_

* SINGA will be presented at `REWORK <https://www.re-work.co/events/deep-learning-singapore/schedule>`_, 21 Oct, 2016.

* SINGA was presented at `PyDataSG <http://www.meetup.com/PyData-SG/events/229691286/>`_, 16 Aug, 2016.

* **Version 0.3.0** is now available, 20 April, 2016. `Download SINGA v0.3.0 <downloads.html>`_

* **Version 0.2.0** is now available, 14 Jan, 2016. `Download SINGA v0.2.0 <downloads.html>`_.

* SINGA will be presented at `Strata+Hadoop <http://strataconf.com/big-data-conference-sg-2015/public/schedule/detail/45123>`_ on 2 Dec, 2015

* SINGA was presented at `ACM Multimedia <http://www.acmmm.org/2015/at-a-glance/>`_ Best Paper session and Open Source Software Competition session, 26-30 Oct, 2015 (`Slides <http://www.comp.nus.edu.sg/~dbsystem/singa//assets/file/mm2015.ppt>`_)

* **Version 0.1.0** is now available, 8 Oct, 2015. `Download SINGA v0.1.0 <downloads.html>`_.

* SINGA was presented at `workshop on deep learning <http://www.comp.nus.edu.sg/~dbsystem/singa/workshop>`_  held on 16 Sep, 2015

* SINGA was presented at `BOSS <http://boss.dima.tu-berlin.de/>`_ of `VLDB 2015 <http://www.vldb.org/2015/>`_ at Hawaii, 4 Sep, 2015. (slides: `overview <http://www.comp.nus.edu.sg/~dbsystem/singa/assets/file/singa-vldb-boss.pptx>`_, `basic <http://www.comp.nus.edu.sg/~dbsystem/singa/assets/file/basic-user-guide.pptx>`_, `advanced <http://www.comp.nus.edu.sg/~dbsystem/singa/assets/file/advanced-user-guide.pptx>`_)

* SINGA was presented at `ADSC/I2R Deep Learning Workshop <http://adsc.illinois.edu/contact-us>`_, 25 Aug, 2015.

* A tutorial on SINGA was given at VLDB summer school at Tsinghua University,  25-31 July, 2015.

* A half day tutorial on SINGA was given at I2R, 29 June, 2015.

* SINGA was presented at `DanaC <http://danac.org/>`_ of `SIGMOD 2015 <http://www.sigmod2015.org/index.shtml>`_ at Melbourne, 31 May - 4 June, 2015.

* SINGA has been accepted by `Apache Incubator <http://incubator.apache.org/>`_, 17 March, 2015.

Getting Started
---------------
* `Install SINGA <docs/installation.html>`_ via conda, apt-get, or from source.

* Try SINGA on `AWS <https://aws.amazon.com/marketplace/pp/B01NAUAWZW>`_ or via `Docker <https://hub.docker.com/r/nusdbsystem/singa/>`_.

* Refer to the `Jupyter notebooks <http://nbviewer.jupyter.org/github/apache/incubator-singa/blob/master/doc/en/docs/notebook/index.ipynb>`_ for some basic examples and the `model zoo page <./docs/model_zoo/index.html>`_ for more examples.

.. |logo| image:: _static/jupyter.png
   :scale: 25%
   :align: middle
   :target: http://nbviewer.jupyter.org/github/apache/incubator-singa/blob/master/doc/en/docs/notebook/index.ipynb

+---------+
| |logo|  |
+---------+

Documentation
-------------

* Documentation and Python APIs are listed `here <docs.html>`_.
* `C++ APIs <../doxygen/html/index.html>`_ are generated by Doxygen.
* Research publication list is available `here <http://www.comp.nus.edu.sg/~dbsystem/singa/research/publication/>`_.

How to contribute
----------------------

* Please subscribe to our development mailing list dev-subscribe@singa.incubator.apache.org.

* If you find any issues using SINGA, please report it to the `Issue Tracker <https://issues.apache.org/jira/browse/singa>`_.

* You can also contact with `SINGA committers <community/team-list.html>`_ directly.

More details on contributing to SINGA is described `here <develop/how-contribute.html>`_ .

History
------------

SINGA was initiated by the DB System Group at National University of Singapore in 2014, in collaboration with the database group of Zhejiang University.
Please cite the following two papers if you use SINGA in your research:

* B. C. Ooi, K.-L. Tan, S. Wang, W. Wang, Q. Cai, G. Chen, J. Gao, Z. Luo, A. K. H. Tung, Y. Wang, Z. Xie, M. Zhang, and K. Zheng. `SINGA: A distributed deep learning platform <http://www.comp.nus.edu.sg/~ooibc/singaopen-mm15.pdf>`_. ACM Multimedia (Open Source Software Competition) 2015 (`BibTex <http://www.comp.nus.edu.sg/~dbsystem/singa//assets/file/bib-oss.txt>`_).

* W. Wang, G. Chen, T. T. A. Dinh, B. C. Ooi, K.-L.Tan, J. Gao, and S. Wang. `SINGA: putting deep learning in the hands of multimedia users <http://www.comp.nus.edu.sg/~ooibc/singa-mm15.pdf>`_. ACM Multimedia 2015 (`BibTex <http://www.comp.nus.edu.sg/~dbsystem/singa//assets/file/bib-singa.txt>`_, `Slides <http://www.comp.nus.edu.sg/~dbsystem/singa/assets/file/mm2015.ppt>`_).

Rafiki is a sub module of SINGA. Please cite the following paper if you use Rafiki in your research:

* Wei Wang, Jinyang Gao, Meihui Zhang, Sheng Wang, Gang Chen, Teck Khim Ng, Beng Chin Ooi, Jie Shao, Moaz Reyad. `Rafiki: Machine Learning as an Analytics Service System <http://www.vldb.org/pvldb/vol12/p128-wang.pdf>`_. `VLDB 2019 <http://vldb.org/2019/>`_ (`BibTex <https://dblp.org/rec/bib2/journals/pvldb/WangWGZCNOS18.bib>`_).

Companies like `NetEase <http://tech.163.com/17/0602/17/CLUL016I00098GJ5.html>`_, `yzBigData <http://www.yzbigdata.com/en/index.html>`_ and `Shentilium <https://shentilium.com/>`_ are using SINGA for their applications.

.. toctree::
   :hidden:

   docs/index
   downloads

.. toctree::
   :hidden:
   :maxdepth: 2
   :caption: Development

   develop/schedule
   develop/how-contribute
   develop/contribute-code
   develop/contribute-docs
   develop/how-to-release

.. toctree::
   :hidden:
   :maxdepth: 2
   :caption: Community

   community/source-repository
   community/mail-lists
   community/issue-tracking
   community/team-list



License
----------
SINGA is released under `Apache License Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`_.

Disclaimers
-----------

Apache SINGA is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF.

