Repository: arogozhnikov/einops (language: python)

Issue:
Torch `Rearrange` layer is unused in one of tests
**Describe the bug**
In the [tests for the torch Rearrange and Reduce layers](https://github.com/arogozhnikov/einops/blob/fdfb9da59dd9552f3d69e3bfe87b4f400fa2b383/tests/test_layers.py#L190), the Reduce layer is used twice but the Rearrange layer is not used at all and therefore not tested.

**Reproduction steps**
Run the relevant test

**Expected behavior**
The Rearrange layer should be used in the test for whether torch layers are working

**Your platform**
N/A



Discussion / hints:
This is not a big deal, but thanks for flagging - I'll add Rearrange there.
No worries - saw it in passing and thought it would be worth pointing out.

Fix patch:
diff --git a/.github/workflows/deploy_to_pypi.yml b/.github/workflows/deploy_to_pypi.yml
new file mode 100644
index 00000000..639e5918
--- /dev/null
+++ b/.github/workflows/deploy_to_pypi.yml
@@ -0,0 +1,27 @@
+name: Deploy to pypi
+
+on:
+    release:
+        types: [created]
+
+jobs:
+    publish:
+        runs-on: ubuntu-latest
+        steps:
+            - name: Checkout sources
+              uses: actions/checkout@v2
+
+            - name: Set up Python
+              uses: actions/setup-python@v2
+              with:
+                  python-version: "3.8"
+
+            - name: Install dependencies
+              run: |
+                  pip install .
+            - name: Publish einops to PyPi
+              env:
+                  TWINE_USERNAME: "__token__"
+                  TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
+              run: |
+                  source scripts/deploy_to_pypi.sh
diff --git a/README.md b/README.md
index 87d9deff..1b5091a7 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-<!-- this link magically rendered as video -->
+<!-- this link magically rendered as video, unfortunately not in docs -->
 
 <!-- https://user-images.githubusercontent.com/6318811/116849688-0ca41c00-aba4-11eb-8ccf-74744f6cbc23.mp4 -->
 
@@ -43,26 +43,16 @@ Supports numpy, pytorch, tensorflow, and [others](#supported-frameworks).
 
 ## Contents
 
+- [Installation](#Installation)
 - [Documentation](https://einops.rocks/)
 - [Tutorial](#Tutorials) 
 - [API micro-reference](#API)
-- [Installation](#Installation)
-- [Naming](#Naming)
 - [Why using einops](#Why-using-einops-notation)
 - [Supported frameworks](#Supported-frameworks)
 - [Contributing](#Contributing)
-- [Github repository (for issues/questions)](https://github.com/arogozhnikov/einops)
-
-
-## Tutorials
-
-Tutorials are the most convenient way to see `einops` in action
-
-- part 1: [einops fundamentals](https://github.com/arogozhnikov/einops/blob/master/docs/1-einops-basics.ipynb) 
-- part 2: [einops for deep learning](https://github.com/arogozhnikov/einops/blob/master/docs/2-einops-for-deep-learning.ipynb)
-- part 3: [real code fragments improved with einops](https://arogozhnikov.github.io/einops/pytorch-examples.html) (so far only for pytorch)   
+- [Repository](https://github.com/arogozhnikov/einops) and [discussions](https://github.com/arogozhnikov/einops/discussions)
 
-## Installation
+## Installation  <a name="Installation"></a>
 
 Plain and simple:
 ```bash
@@ -78,7 +68,16 @@ pip install https://github.com/arogozhnikov/einops/archive/master.zip
 ```
 -->
 
-## API 
+## Tutorials <a name="Tutorials"></a>
+
+Tutorials are the most convenient way to see `einops` in action
+
+- part 1: [einops fundamentals](https://github.com/arogozhnikov/einops/blob/master/docs/1-einops-basics.ipynb) 
+- part 2: [einops for deep learning](https://github.com/arogozhnikov/einops/blob/master/docs/2-einops-for-deep-learning.ipynb)
+- part 3: [improve pytorch code with einops](https://arogozhnikov.github.io/einops/pytorch-examples.html)   
+
+
+## API <a name="API"></a>
 
 `einops` has a minimalistic yet powerful API.
 
@@ -145,14 +144,14 @@ parse_shape(input_tensor, 'batch _ h w') # e.g {'batch': 64, 'h': 128, 'w': 160}
 ```
 -->
 
-## Naming
+## Naming <a name="Naming"></a>
 
 `einops` stands for Einstein-Inspired Notation for operations 
 (though "Einstein operations" is more attractive and easier to remember).
 
 Notation was loosely inspired by Einstein summation (in particular by `numpy.einsum` operation).
 
-## Why use `einops` notation?!
+## Why use `einops` notation?! <a name="Why-using-einops-notation"></a>
 
 
 ### Semantic information (being verbose in expectations)
@@ -258,8 +257,9 @@ repeat(image, 'h w -> h (tile w)', tile=2)  # in mxnet
 ... (etc.)
 ```
 
+Testimonials provide user's perspective on the same question. 
 
-## Supported frameworks
+## Supported frameworks <a name="Supported-frameworks"></a>
 
 Einops works with ...
 
@@ -274,14 +274,15 @@ Einops works with ...
 - [mxnet](https://mxnet.apache.org/) (experimental)
 
 
-## Contributing 
+## Contributing <a name="Contributing"></a>
 
 Best ways to contribute are
 
 - spread the word about `einops`
-- if you like explaining things, alternative tutorials are welcome
-- translating examples in languages other than English is also a good idea
-- use `einops` notation in your papers to strictly define used operations!
+- if you like explaining things, more tutorials/tear-downs of implementations is welcome
+- tutorials in other languages are very welcome
+- do you have project/code example to share? Let me know in github discussions
+- use `einops` in your papers!
 
 ## Supported python versions
 
diff --git a/docs/pages/projects.md b/docs/pages/projects.md
new file mode 100644
index 00000000..9471de14
--- /dev/null
+++ b/docs/pages/projects.md
@@ -0,0 +1,75 @@
+Einops tutorials cover multiple einops usages (and you'd better first follow tutorials), 
+but it can also help to see einops in action.
+
+## Selected projects
+
+Here are some open-source projects that can teach how to leverage einops for your problems
+
+- [lambda networks](https://www.youtube.com/watch?v=3qxJ2WD8p4w) (non-conventional architecture) implementation by [@lucidrains](https://github.com/lucidrains)
+    - nice demonstration how clearer code can be with einops, even compared to verbal description 
+    - <https://github.com/lucidrains/lambda-networks>
+
+
+- capsule networks (aka capsnets) [implemented in einops](https://github.com/arogozhnikov/readable_capsnet)
+    - blazingly fast, concise, and 3x-more memory efficient capsule networks, written with einops  
+
+
+- @lucidrains has a dramatic [collection of vision transformers](https://github.com/lucidrains/vit-pytorch)
+    - there is a plenty of good examples how to use einops efficiently
+
+
+- [NuX](https://github.com/Information-Fusion-Lab-Umass/NuX) - normalizing flows in Jax
+    - different rearrangement patterns in normalizing flows have nice mapping to einops
+
+
+- As for video recognition, look at [MotionFormer](https://github.com/facebookresearch/Motionformer) 
+  and [TimeSFormer](https://github.com/lucidrains/TimeSformer-pytorch) implementations
+
+
+- For protein folding, see [implementation](https://github.com/lucidrains/invariant-point-attention)
+  of invariant point attention from alphafold 2
+
+## Non-official tutorials about einops
+
+Tutorial in the AI summer about einops and einsum:
+<https://theaisummer.com/einsum-attention/>
+
+Implementing visual transformer in pytorch:
+<https://towardsdatascience.com/implementing-visualttransformer-in-pytorch-184f9f16f632>
+
+ML TLDR twitter thread on einops:
+<https://twitter.com/mlsummaries/status/1400505282543955970>
+
+Book "Deep Reinforcement Learning in Action" by Brandon Brown & Alexander Zai
+contains an introduction into einops in chapter 10.
+
+[comment]: <> (MLP mixer introduction)
+[comment]: <> (https://www.youtube.com/watch?v=HqytB2GUbHA)
+
+## Other einops-based projects worth looking at:
+
+(ordered randomly)
+
+- <https://github.com/The-AI-Summer/self-attention-cv>
+- <https://github.com/lucidrains/perceiver-pytorch>
+- <https://github.com/hila-chefer/Transformer-Explainability>
+- [https://github.com/microsoft/CvT](https://github.com/microsoft/CvT/blob/4cedb05b343e13ab08c0a29c5166b6e94c751112/lib/models/cls_cvt.py)
+- <https://github.com/lucidrains/g-mlp-gpt>
+- <https://github.com/zju3dv/LoFTR>
+- <https://github.com/WangFeng18/Swin-Transformer>
+- <https://github.com/kwea123/CasMVSNet_pl>
+- <https://github.com/kakao/DAFT>
+- <https://github.com/lucidrains/multistream-transformers>
+- <https://github.com/poets-ai/elegy>
+- <https://github.com/lucidrains/ponder-transformer>
+- <https://github.com/isaaccorley/torchrs>
+- <https://github.com/microsoft/esvit>
+- <https://github.com/zyddnys/manga-image-translator>
+- <https://github.com/google/jax-cfd>
+
+
+## Related projects:
+
+- [numpy.einsum](https://numpy.org/doc/stable/reference/generated/numpy.einsum.html) &mdash; grand-dad of einops, this operation is now available in all modern DL frameworks 
+- einops in rust language <https://docs.rs/einops/0.1.0/einops>
+- tensorcast in Julia language <https://juliahub.com/ui/Packages/TensorCast>
\ No newline at end of file
diff --git a/mkdocs.yml b/mkdocs.yml
index a1bc5a07..2ba4511f 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -20,6 +20,8 @@ nav:
       rearrange: api/rearrange.md
       reduce: api/reduce.md
       repeat: api/repeat.md
+  - Testimonials: pages/testimonials.md
+  - Projects: pages/projects.md
 extra:
   search:
     language: en
diff --git a/scripts/deploy-docs.sh b/scripts/deploy-docs.sh
index f1c1a285..14d3ad83 100644
--- a/scripts/deploy-docs.sh
+++ b/scripts/deploy-docs.sh
@@ -1,2 +1,4 @@
-mkdocs build
-mkdocs gh-deploy
\ No newline at end of file
+# auto pushes to github
+pip install -r scripts/requirements-dev.txt \
+&& mkdocs build \
+&& mkdocs gh-deploy
\ No newline at end of file
diff --git a/scripts/run-docs.sh b/scripts/run-docs.sh
index ac413384..eac0f8cc 100644
--- a/scripts/run-docs.sh
+++ b/scripts/run-docs.sh
@@ -1,1 +1,3 @@
-mkdocs serve
\ No newline at end of file
+# serves documentation locally, source from repo root dir
+pip install -r scripts/requirements-dev.txt \
+&& mkdocs serve
\ No newline at end of file


Test patch:
diff --git a/docs/pages/testimonials.md b/docs/pages/testimonials.md
new file mode 100644
index 00000000..22f8f3f5
--- /dev/null
+++ b/docs/pages/testimonials.md
@@ -0,0 +1,138 @@
+<style>
+.md-typeset blockquote {
+    background-color: rgba(63,127,127,0.29);
+    margin-top: 2.5em;
+    margin-bottom: -0.5em;
+    margin-right: 3em;
+    color: #333;
+}
+blockquote + p {
+    text-align: right;
+    padding-right: 5em;
+}
+</style>
+Einops was created three years ago, and never hit big ML news.
+However, little by little and step by step it sneaked into every major AI lab.
+
+This all happened by word of mouth and by sharing code snippets:
+
+
+> Einops simplifies and clarifies array/tensor manipulation. 👍 <br />
+> You really have to try it out, you'll love it: https://github.com/arogozhnikov/einops <br />
+> Plus it supports NumPy, TensorFlow, PyTorch, and more.
+
+Aurélien Geron, <br />
+author of "Hands-On Machine Learning with Scikit-Learn and TensorFlow." <br /> 
+Former PM of YouTube video classification.
+[(ref)](https://twitter.com/aureliengeron/status/1382829421967515648)
+
+
+> This is your daily reminder to *never* trust pytorch's native reshape/view. <br /> 
+> Always use einops! 
+> 
+> (Just spend 1 h debugging code and it turned out tensor.view was shuffling the tensor in a weird way) 
+
+
+Tom Lieberum, University of Amsterdam
+[(ref)](https://twitter.com/lieberum_t/status/1427282842250358787)
+
+
+> TIL einops can be faster than raw PyTorch 🤯
+
+Zach Mueller, fastai
+[(ref)](https://twitter.com/TheZachMueller/status/1418003372494426113)
+
+> einops are also a joy to work with!
+
+Norman Casagrande, Deepmind
+[(ref)](https://twitter.com/nova77t/status/1419405150805008387)
+
+
+> &mdash; And btw I estimate that AI research suffers globally from a 5% loss of productivity because einops are not included in 
+@PyTorch by default.
+>
+> &mdash; Might be true for research, but not likely to be true for engineering. I don't think a lot of people in the industry use PyTorch directly [...]
+>
+> &mdash; That’s why it’s 5% and not 30%
+>
+> &mdash; E-xa-ctly
+
+[Discussion thread](https://twitter.com/francoisfleuret/status/1409141186326106114)
+
+
+> After a while, it feels like einsum+einops is all you need ;) [...]
+ 
+Tim Rocktäschel, Facebook AI Research 
+[(ref)](https://twitter.com/_rockt/status/1390049226193788930)
+
+
+> Yes, I am also using einops in that snippet! It's great! <br /> 
+> I wished I knew about it from the start when it was created
+
+Tim Dettmers, PhD Student at UoW and visiting researcher at Facebook AI
+[(ref)](https://twitter.com/Tim_Dettmers/status/1390027329351520256)
+
+> A little late to the party, but einops (https://github.com/arogozhnikov/einops) is a massive improvement to deep learning code readability. I love this!
+
+Daniel Havir, Apple [(ref)](https://twitter.com/danielhavir/status/1389070232853966849)
+
+
+Comment: some of 'late to the party' tweets are 2 years old now. You can never be late to this party.
+
+
+
+> I recently discovered the beauty of torch.einsum and einops.rearrange <br /> 
+> and at this point I'm confused why I even bothered with other tensor operations in the first place.
+
+Robin M. Schmidt, AI/ML Resident at Apple [(ref)](https://twitter.com/robinschmidt_/status/1363709832788852736)
+
+ 
+[comment]: <> (> The einops library, in particular, is magical. Best thing since baked bread and brewed beer.)
+
+> I end up using einops for ridiculously simple things, <br />
+> simply to be nice to my future self (because the code takes so little effort to read).
+
+Nasim Rahaman, MILA [(ref)](https://twitter.com/nasim_rahaman/status/1390027557546901504)
+
+> I love Einops for this kind of stuff, it makes code very readable, <br /> 
+> even if you are just doing a simple squeeze or expand_dims. [...]
+
+Cristian Garcia, ML Engineer @quansightai, [(ref)](https://twitter.com/cgarciae88/status/1331968395110211586)
+
+> i might be late to the party, but einsum and the einops package are unbelievably useful
+
+Samson Koelle, Stat PhD candidate at UoW, [(ref)](https://twitter.com/SeattleStatSam/status/1338673646898794496)
+
+> I really recommend einops for tensor shape manipulation
+
+
+Alex Mordvintsev, DeepDream creator, [(ref)](https://twitter.com/zzznah/status/1315297985585123328)
+
+ 
+> The einops Python package is worth checking out: 
+> it provides a powerful declarative interface 
+> for manipulating and reshaping multi-dimensional arrays https://github.com/arogozhnikov/einops
+
+Jake VanderPlas, 
+Google Research, core contributor to Altair, AstroML, scikit-learn, etc.
+[(ref)](https://twitter.com/jakevdp/status/1299012119761833989)
+
+
+
+> I can't believe after this many years of programming with NumPy/PyTorch/TensorFlow, I didn't know about 𝚎𝚒𝚗𝚜𝚞𝚖. [...] <br/>
+> &mdash; Arash Vahdat
+> 
+> They smell like regexp to me -- concise, but I know it is going to take effort to understand or modify them in the future.  <br/>
+> &mdash; John Carmack
+> 
+> I have a much easier time to read einsum than any equivalent combinations of matmul, reshape, broadcasting... you name it.
+> Regexps are ad-hoc, subtle and cryptic.
+> 
+> Einstein summation is uniform, succinct with simple, clear semantics. <br />
+> Ein sum to rule them all ;) <br />
+> &mdash; Christian Szegedy
+> 
+> The einops library, in particular, is magical. Best thing since baked bread and brewed beer. <br />
+> &mdash; @aertherks
+
+[Discussion thread](https://twitter.com/aertherks/status/1357054506656165889) 
\ No newline at end of file
diff --git a/tests/test_layers.py b/tests/test_layers.py
index 7c9133ce..32c5cb88 100644
--- a/tests/test_layers.py
+++ b/tests/test_layers.py
@@ -199,7 +199,8 @@ def create_model(use_reduce=False):
                 Conv2d(3, 6, kernel_size=5),
                 Reduce('b c (h h2) (w w2) -> b c h w', 'max', h2=2, w2=2) if use_reduce else MaxPool2d(kernel_size=2),
                 Conv2d(6, 16, kernel_size=5),
-                Reduce('b c (h h2) (w w2) -> b (c h w)', 'max', h2=2, w2=2),
+                Reduce('b c (h h2) (w w2) -> b c h w', 'max', h2=2, w2=2),
+                Rearrange('b c h w -> b (c h w)'),
                 Linear(16 * 5 * 5, 120),
                 ReLU(),
                 Linear(120, 84),