.. 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/apache/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.

