Add ONNX export for ViT
Author: lewtun
Pull request: yes

# What does this PR do?

This PR enables the export of Vision Transformers (ViT) to ONNX with the following features:

* `default`
* `image-classification`

To enable this new modality, I had to significantly refactor the internals of the ONNX exporter because we need a way to pass the feature extractor instead of the tokenizer. 

Thanks to a tip from @LysandreJik I replaced the positional `tokenizer` argument in various functions with a new `preprocessor` argument that can be a tokenizer or feature extractor (and possibly a processor in future). This should guarantee backwards compatibility for users who chose to use the Python API instead of the `transformers.onnx` CLI.

## Usage

```python
import requests
import numpy as np
from PIL import Image
from onnxruntime import InferenceSession
from transformers import AutoConfig, AutoFeatureExtractor, AutoModelForImageClassification

# Export ViT checkpoint with image classification head
model_ckpt = "google/vit-base-patch16-224"
!python -m transformers.onnx --model={model_ckpt} --feature=image-classification onnx/

# Download an image of two cute cats - naturally ;-)
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
image = Image.open(requests.get(url, stream=True).raw)

# Instantiate config and feature extractor
config = AutoConfig.from_pretrained(model_ckpt)
feature_extractor = AutoFeatureExtractor.from_pretrained(model_ckpt)
inputs = feature_extractor(image, return_tensors="np")

# Create ONNX Runtime session
session = InferenceSession("onnx/model.onnx", providers=["CPUExecutionProvider"])
outputs = session.run(["logits"], dict(inputs))
predicted_class_idx = np.argmax(outputs[0])
# Returns Predicted class: Egyptian cat
print("Predicted class:", config.id2label[predicted_class_idx])
```

Here's two Colab notebooks comparing the inference gains with ORT vs vanilla PyTorch (~20-30% faster on CPU, ~5% faster on GPU):

* [CPU notebook](https://colab.research.google.com/drive/1QCTNRsctMCdvMRiWmAnbEPHJ9rmkAbAP?usp=sharing)
* [GPU notebook](https://colab.research.google.com/drive/1SZrCqvJzm6z5xjb_01-fnmTk-boGYalA?usp=sharing)

## Todo

- [x] Add deprecation warning if user passes `tokenizer` as keyword argument
- [x] Run an inference test to see if we get any speed-up over vanilla PyTorch (maybe)

Comments:
The docs for this PR live [here](https://moon-ci-docs.huggingface.co/docs/transformers/pr_15658). All of your documentation changes will be reflected on that endpoint.

While testing this branch on Colab, I discovered a weird bug when trying to run inference in ONNX Runtime with `torch` v1.10.2:

```
RuntimeException: [ONNXRuntimeError] : 6 : RUNTIME_EXCEPTION : Non-zero status code returned while running Reshape node. Name:'Reshape_42' Status Message: /Users/runner/work/1/s/onnxruntime/core/providers/cpu/tensor/reshape_helper.h:42 onnxruntime::ReshapeHelper::ReshapeHelper(const onnxruntime::TensorShape &, std::vector<int64_t> &, bool) gsl::narrow_cast<int64_t>(input_shape.Size()) == size was false. The input tensor cannot be reshaped to the requested shape. Input shape:{1,197,768}, requested shape:{2,197,12,64}
```

Curiously, there is no problem running inference with `torch` v1.9, so something seems to have changed in the `torch` ONNX exporter in the latest version. I'm currently investigating what the source of the problem is ...

I've implemented a workaround for the problems with exporting dynamic axes in `torch` v1.10.x, as well as integrated all your feedback. Apart from that, I think this PR is ready for another round of review :)

Super happy to see this merged! 🤗