We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Make categorical_input/numerical_input optional for TabularData.from_df
## 🐛 Bug
If I have only numerical features then I still have to pass an empty list for the categorical_input. It can be optional.
![image](https://user-images.githubusercontent.com/21018714/107743211-7ac00c00-6d36-11eb-918f-631e20c822ec.png)

### To Reproduce

Steps to reproduce the behavior:

1. df = pd.DataFrame({'digit': [1,2,3], 'odd_even':[0,1,0]})
2. datamodule = TabularData.from_df(df, 'odd_even', 
                    numerical_input=['digit'],
                   )

```
TypeError                                 Traceback (most recent call last)
<ipython-input-122-405a8bb49976> in <module>
      1 datamodule = TabularData.from_df(final_data, 'target', 
----> 2                     numerical_input=train_x.columns.tolist(),
      3 #                     categorical_input=[],
      4                    )

TypeError: from_df() missing 1 required positional argument: 'categorical_input'
```

#### Code sample
```
df = pd.DataFrame({'digit': [1,2,3], 'odd_even':[0,1,0]})
datamodule = TabularData.from_df(df, 'odd_even', 
                    numerical_input=['digit'],
                   )
```

### Expected behaviour
If only one of categorical or numerical input is passed then users should not be forced to enter an empty list.

### Environment

 - PyTorch Version (e.g., 1.0): '1.7.1'
 - OS (e.g., Linux): MacOS
 - How you installed PyTorch (`conda`, `pip`, source): pip
 - Python version:Python 3.7.9


> I would love to start my contribution to Flash by fixing this issue.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `flash/tabular/classification/data/data.py`
Content:
```
1 # Copyright The PyTorch Lightning team.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 from typing import Any, Dict, List, Optional
15 
16 import numpy as np
17 import pandas as pd
18 from pandas.core.frame import DataFrame
19 from sklearn.model_selection import train_test_split
20 from torch import Tensor
21 
22 from flash.core.classification import ClassificationDataPipeline
23 from flash.core.data import DataPipeline
24 from flash.core.data.datamodule import DataModule
25 from flash.core.data.utils import _contains_any_tensor
26 from flash.tabular.classification.data.dataset import (
27     _compute_normalization,
28     _dfs_to_samples,
29     _generate_codes,
30     _impute,
31     _pre_transform,
32     PandasDataset,
33 )
34 
35 
36 class TabularDataPipeline(ClassificationDataPipeline):
37 
38     def __init__(
39         self,
40         categorical_input: List,
41         numerical_input: List,
42         target: str,
43         mean: DataFrame,
44         std: DataFrame,
45         codes: Dict,
46     ):
47         self._categorical_input = categorical_input
48         self._numerical_input = numerical_input
49         self._target = target
50         self._mean = mean
51         self._std = std
52         self._codes = codes
53 
54     def before_collate(self, samples: Any) -> Any:
55         """Override to apply transformations to samples"""
56         if _contains_any_tensor(samples, dtype=(Tensor, np.ndarray)):
57             return samples
58         if isinstance(samples, str):
59             samples = pd.read_csv(samples)
60         if isinstance(samples, DataFrame):
61             samples = [samples]
62         dfs = _pre_transform(
63             samples, self._numerical_input, self._categorical_input, self._codes, self._mean, self._std
64         )
65         return _dfs_to_samples(dfs, self._categorical_input, self._numerical_input)
66 
67 
68 class TabularData(DataModule):
69     """Data module for tabular tasks"""
70 
71     def __init__(
72         self,
73         train_df: DataFrame,
74         categorical_input: List,
75         numerical_input: List,
76         target: str,
77         valid_df: Optional[DataFrame] = None,
78         test_df: Optional[DataFrame] = None,
79         batch_size: int = 2,
80         num_workers: Optional[int] = None,
81     ):
82         dfs = [train_df]
83         self._test_df = None
84 
85         if valid_df is not None:
86             dfs.append(valid_df)
87 
88         if test_df is not None:
89             # save for predict function
90             self._test_df = test_df.copy()
91             self._test_df.drop(target, axis=1)
92             dfs.append(test_df)
93 
94         # impute missing values
95         dfs = _impute(dfs, numerical_input)
96 
97         # compute train dataset stats
98         self.mean, self.std = _compute_normalization(dfs[0], numerical_input)
99 
100         if dfs[0][target].dtype == object:
101             # if the target is a category, not an int
102             self.target_codes = _generate_codes(dfs, [target])
103         else:
104             self.target_codes = None
105 
106         self.codes = _generate_codes(dfs, categorical_input)
107 
108         dfs = _pre_transform(
109             dfs, numerical_input, categorical_input, self.codes, self.mean, self.std, target, self.target_codes
110         )
111 
112         # normalize
113         self.cat_cols = categorical_input
114         self.num_cols = numerical_input
115 
116         self._num_classes = len(train_df[target].unique())
117 
118         train_ds = PandasDataset(dfs[0], categorical_input, numerical_input, target)
119         valid_ds = PandasDataset(dfs[1], categorical_input, numerical_input, target) if valid_df is not None else None
120         test_ds = PandasDataset(dfs[-1], categorical_input, numerical_input, target) if test_df is not None else None
121         super().__init__(train_ds, valid_ds, test_ds, batch_size=batch_size, num_workers=num_workers)
122 
123     @property
124     def num_classes(self) -> int:
125         return self._num_classes
126 
127     @property
128     def num_features(self) -> int:
129         return len(self.cat_cols) + len(self.num_cols)
130 
131     @classmethod
132     def from_df(
133         cls,
134         train_df: DataFrame,
135         target: str,
136         categorical_input: List,
137         numerical_input: List,
138         valid_df: Optional[DataFrame] = None,
139         test_df: Optional[DataFrame] = None,
140         batch_size: int = 8,
141         num_workers: Optional[int] = None,
142         val_size: float = None,
143         test_size: float = None,
144     ):
145         """Creates a TabularData object from pandas DataFrames.
146 
147         Args:
148             train_df: train data DataFrame
149             target: The column containing the class id.
150             categorical_input: The list of categorical columns.
151             numerical_input: The list of numerical columns.
152             valid_df: validation data DataFrame
153             test_df: test data DataFrame
154             batch_size: the batchsize to use for parallel loading. Defaults to 64.
155             num_workers: The number of workers to use for parallelized loading.
156                 Defaults to None which equals the number of available CPU threads.
157             val_size: float between 0 and 1 to create a validation dataset from train dataset
158             test_size: float between 0 and 1 to create a test dataset from train validation
159 
160         Returns:
161             TabularData: The constructed data module.
162 
163         Examples::
164 
165             text_data = TextClassificationData.from_files("train.csv", label_field="class", text_field="sentence")
166         """
167         if valid_df is None and isinstance(val_size, float) and isinstance(test_size, float):
168             assert 0 < val_size and val_size < 1
169             assert 0 < test_size and test_size < 1
170             train_df, valid_df = train_test_split(train_df, test_size=(val_size + test_size))
171 
172         if test_df is None and isinstance(test_size, float):
173             assert 0 < test_size and test_size < 1
174             valid_df, test_df = train_test_split(valid_df, test_size=test_size)
175 
176         datamodule = cls(
177             train_df=train_df,
178             target=target,
179             categorical_input=categorical_input,
180             numerical_input=numerical_input,
181             valid_df=valid_df,
182             test_df=test_df,
183             batch_size=batch_size,
184             num_workers=num_workers,
185         )
186         datamodule.data_pipeline = TabularDataPipeline(
187             categorical_input, numerical_input, target, datamodule.mean, datamodule.std, datamodule.codes
188         )
189 
190         return datamodule
191 
192     @classmethod
193     def from_csv(
194         cls,
195         train_csv: str,
196         target: str,
197         categorical_input: List,
198         numerical_input: List,
199         valid_csv: Optional[str] = None,
200         test_csv: Optional[str] = None,
201         batch_size: int = 8,
202         num_workers: Optional[int] = None,
203         val_size: Optional[float] = None,
204         test_size: Optional[float] = None,
205         **pandas_kwargs,
206     ):
207         """Creates a TextClassificationData object from pandas DataFrames.
208 
209         Args:
210             train_csv: train data csv file.
211             target: The column containing the class id.
212             categorical_input: The list of categorical columns.
213             numerical_input: The list of numerical columns.
214             valid_csv: validation data csv file.
215             test_csv: test data csv file.
216             batch_size: the batchsize to use for parallel loading. Defaults to 64.
217             num_workers: The number of workers to use for parallelized loading.
218                 Defaults to None which equals the number of available CPU threads.
219             val_size: float between 0 and 1 to create a validation dataset from train dataset
220             test_size: float between 0 and 1 to create a test dataset from train validation
221 
222         Returns:
223             TabularData: The constructed data module.
224 
225         Examples::
226 
227             text_data = TabularData.from_files("train.csv", label_field="class", text_field="sentence")
228         """
229         train_df = pd.read_csv(train_csv, **pandas_kwargs)
230         valid_df = pd.read_csv(valid_csv, **pandas_kwargs) if valid_csv is not None else None
231         test_df = pd.read_csv(test_csv, **pandas_kwargs) if test_csv is not None else None
232         datamodule = cls.from_df(
233             train_df, target, categorical_input, numerical_input, valid_df, test_df, batch_size, num_workers, val_size,
234             test_size
235         )
236         return datamodule
237 
238     @property
239     def emb_sizes(self) -> list:
240         """Recommended embedding sizes."""
241 
242         # https://developers.googleblog.com/2017/11/introducing-tensorflow-feature-columns.html
243         # The following "formula" provides a general rule of thumb about the number of embedding dimensions:
244         # embedding_dimensions =  number_of_categories**0.25
245 
246         num_classes = [len(self.codes[cat]) for cat in self.cat_cols]
247         emb_dims = [max(int(n**0.25), 16) for n in num_classes]
248         return list(zip(num_classes, emb_dims))
249 
250     @staticmethod
251     def default_pipeline() -> DataPipeline():
252         # TabularDataPipeline depends on the data
253         return DataPipeline()
254
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/flash/tabular/classification/data/data.py b/flash/tabular/classification/data/data.py
--- a/flash/tabular/classification/data/data.py
+++ b/flash/tabular/classification/data/data.py
@@ -71,9 +71,9 @@
     def __init__(
         self,
         train_df: DataFrame,
-        categorical_input: List,
-        numerical_input: List,
         target: str,
+        categorical_input: Optional[List] = None,
+        numerical_input: Optional[List] = None,
         valid_df: Optional[DataFrame] = None,
         test_df: Optional[DataFrame] = None,
         batch_size: int = 2,
@@ -82,6 +82,12 @@
         dfs = [train_df]
         self._test_df = None
 
+        if categorical_input is None and numerical_input is None:
+            raise RuntimeError('Both `categorical_input` and `numerical_input` are None!')
+
+        categorical_input = categorical_input if categorical_input is not None else []
+        numerical_input = numerical_input if numerical_input is not None else []
+
         if valid_df is not None:
             dfs.append(valid_df)
 
@@ -133,8 +139,8 @@
         cls,
         train_df: DataFrame,
         target: str,
-        categorical_input: List,
-        numerical_input: List,
+        categorical_input: Optional[List] = None,
+        numerical_input: Optional[List] = None,
         valid_df: Optional[DataFrame] = None,
         test_df: Optional[DataFrame] = None,
         batch_size: int = 8,
@@ -194,8 +200,8 @@
         cls,
         train_csv: str,
         target: str,
-        categorical_input: List,
-        numerical_input: List,
+        categorical_input: Optional[List] = None,
+        numerical_input: Optional[List] = None,
         valid_csv: Optional[str] = None,
         test_csv: Optional[str] = None,
         batch_size: int = 8,

{"golden_diff": "diff --git a/flash/tabular/classification/data/data.py b/flash/tabular/classification/data/data.py\n--- a/flash/tabular/classification/data/data.py\n+++ b/flash/tabular/classification/data/data.py\n@@ -71,9 +71,9 @@\n     def __init__(\n         self,\n         train_df: DataFrame,\n-        categorical_input: List,\n-        numerical_input: List,\n         target: str,\n+        categorical_input: Optional[List] = None,\n+        numerical_input: Optional[List] = None,\n         valid_df: Optional[DataFrame] = None,\n         test_df: Optional[DataFrame] = None,\n         batch_size: int = 2,\n@@ -82,6 +82,12 @@\n         dfs = [train_df]\n         self._test_df = None\n \n+        if categorical_input is None and numerical_input is None:\n+            raise RuntimeError('Both `categorical_input` and `numerical_input` are None!')\n+\n+        categorical_input = categorical_input if categorical_input is not None else []\n+        numerical_input = numerical_input if numerical_input is not None else []\n+\n         if valid_df is not None:\n             dfs.append(valid_df)\n \n@@ -133,8 +139,8 @@\n         cls,\n         train_df: DataFrame,\n         target: str,\n-        categorical_input: List,\n-        numerical_input: List,\n+        categorical_input: Optional[List] = None,\n+        numerical_input: Optional[List] = None,\n         valid_df: Optional[DataFrame] = None,\n         test_df: Optional[DataFrame] = None,\n         batch_size: int = 8,\n@@ -194,8 +200,8 @@\n         cls,\n         train_csv: str,\n         target: str,\n-        categorical_input: List,\n-        numerical_input: List,\n+        categorical_input: Optional[List] = None,\n+        numerical_input: Optional[List] = None,\n         valid_csv: Optional[str] = None,\n         test_csv: Optional[str] = None,\n         batch_size: int = 8,\n", "issue": "Make categorical_input/numerical_input optional for TabularData.from_df\n## \ud83d\udc1b Bug\r\nIf I have only numerical features then I still have to pass an empty list for the categorical_input. It can be optional.\r\n![image](https://user-images.githubusercontent.com/21018714/107743211-7ac00c00-6d36-11eb-918f-631e20c822ec.png)\r\n\r\n### To Reproduce\r\n\r\nSteps to reproduce the behavior:\r\n\r\n1. df = pd.DataFrame({'digit': [1,2,3], 'odd_even':[0,1,0]})\r\n2. datamodule = TabularData.from_df(df, 'odd_even', \r\n                    numerical_input=['digit'],\r\n                   )\r\n\r\n```\r\nTypeError                                 Traceback (most recent call last)\r\n<ipython-input-122-405a8bb49976> in <module>\r\n      1 datamodule = TabularData.from_df(final_data, 'target', \r\n----> 2                     numerical_input=train_x.columns.tolist(),\r\n      3 #                     categorical_input=[],\r\n      4                    )\r\n\r\nTypeError: from_df() missing 1 required positional argument: 'categorical_input'\r\n```\r\n\r\n#### Code sample\r\n```\r\ndf = pd.DataFrame({'digit': [1,2,3], 'odd_even':[0,1,0]})\r\ndatamodule = TabularData.from_df(df, 'odd_even', \r\n                    numerical_input=['digit'],\r\n                   )\r\n```\r\n\r\n### Expected behaviour\r\nIf only one of categorical or numerical input is passed then users should not be forced to enter an empty list.\r\n\r\n### Environment\r\n\r\n - PyTorch Version (e.g., 1.0): '1.7.1'\r\n - OS (e.g., Linux): MacOS\r\n - How you installed PyTorch (`conda`, `pip`, source): pip\r\n - Python version:Python 3.7.9\r\n\r\n\r\n> I would love to start my contribution to Flash by fixing this issue.\n", "before_files": [{"content": "# Copyright The PyTorch Lightning team.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Any, Dict, List, Optional\n\nimport numpy as np\nimport pandas as pd\nfrom pandas.core.frame import DataFrame\nfrom sklearn.model_selection import train_test_split\nfrom torch import Tensor\n\nfrom flash.core.classification import ClassificationDataPipeline\nfrom flash.core.data import DataPipeline\nfrom flash.core.data.datamodule import DataModule\nfrom flash.core.data.utils import _contains_any_tensor\nfrom flash.tabular.classification.data.dataset import (\n    _compute_normalization,\n    _dfs_to_samples,\n    _generate_codes,\n    _impute,\n    _pre_transform,\n    PandasDataset,\n)\n\n\nclass TabularDataPipeline(ClassificationDataPipeline):\n\n    def __init__(\n        self,\n        categorical_input: List,\n        numerical_input: List,\n        target: str,\n        mean: DataFrame,\n        std: DataFrame,\n        codes: Dict,\n    ):\n        self._categorical_input = categorical_input\n        self._numerical_input = numerical_input\n        self._target = target\n        self._mean = mean\n        self._std = std\n        self._codes = codes\n\n    def before_collate(self, samples: Any) -> Any:\n        \"\"\"Override to apply transformations to samples\"\"\"\n        if _contains_any_tensor(samples, dtype=(Tensor, np.ndarray)):\n            return samples\n        if isinstance(samples, str):\n            samples = pd.read_csv(samples)\n        if isinstance(samples, DataFrame):\n            samples = [samples]\n        dfs = _pre_transform(\n            samples, self._numerical_input, self._categorical_input, self._codes, self._mean, self._std\n        )\n        return _dfs_to_samples(dfs, self._categorical_input, self._numerical_input)\n\n\nclass TabularData(DataModule):\n    \"\"\"Data module for tabular tasks\"\"\"\n\n    def __init__(\n        self,\n        train_df: DataFrame,\n        categorical_input: List,\n        numerical_input: List,\n        target: str,\n        valid_df: Optional[DataFrame] = None,\n        test_df: Optional[DataFrame] = None,\n        batch_size: int = 2,\n        num_workers: Optional[int] = None,\n    ):\n        dfs = [train_df]\n        self._test_df = None\n\n        if valid_df is not None:\n            dfs.append(valid_df)\n\n        if test_df is not None:\n            # save for predict function\n            self._test_df = test_df.copy()\n            self._test_df.drop(target, axis=1)\n            dfs.append(test_df)\n\n        # impute missing values\n        dfs = _impute(dfs, numerical_input)\n\n        # compute train dataset stats\n        self.mean, self.std = _compute_normalization(dfs[0], numerical_input)\n\n        if dfs[0][target].dtype == object:\n            # if the target is a category, not an int\n            self.target_codes = _generate_codes(dfs, [target])\n        else:\n            self.target_codes = None\n\n        self.codes = _generate_codes(dfs, categorical_input)\n\n        dfs = _pre_transform(\n            dfs, numerical_input, categorical_input, self.codes, self.mean, self.std, target, self.target_codes\n        )\n\n        # normalize\n        self.cat_cols = categorical_input\n        self.num_cols = numerical_input\n\n        self._num_classes = len(train_df[target].unique())\n\n        train_ds = PandasDataset(dfs[0], categorical_input, numerical_input, target)\n        valid_ds = PandasDataset(dfs[1], categorical_input, numerical_input, target) if valid_df is not None else None\n        test_ds = PandasDataset(dfs[-1], categorical_input, numerical_input, target) if test_df is not None else None\n        super().__init__(train_ds, valid_ds, test_ds, batch_size=batch_size, num_workers=num_workers)\n\n    @property\n    def num_classes(self) -> int:\n        return self._num_classes\n\n    @property\n    def num_features(self) -> int:\n        return len(self.cat_cols) + len(self.num_cols)\n\n    @classmethod\n    def from_df(\n        cls,\n        train_df: DataFrame,\n        target: str,\n        categorical_input: List,\n        numerical_input: List,\n        valid_df: Optional[DataFrame] = None,\n        test_df: Optional[DataFrame] = None,\n        batch_size: int = 8,\n        num_workers: Optional[int] = None,\n        val_size: float = None,\n        test_size: float = None,\n    ):\n        \"\"\"Creates a TabularData object from pandas DataFrames.\n\n        Args:\n            train_df: train data DataFrame\n            target: The column containing the class id.\n            categorical_input: The list of categorical columns.\n            numerical_input: The list of numerical columns.\n            valid_df: validation data DataFrame\n            test_df: test data DataFrame\n            batch_size: the batchsize to use for parallel loading. Defaults to 64.\n            num_workers: The number of workers to use for parallelized loading.\n                Defaults to None which equals the number of available CPU threads.\n            val_size: float between 0 and 1 to create a validation dataset from train dataset\n            test_size: float between 0 and 1 to create a test dataset from train validation\n\n        Returns:\n            TabularData: The constructed data module.\n\n        Examples::\n\n            text_data = TextClassificationData.from_files(\"train.csv\", label_field=\"class\", text_field=\"sentence\")\n        \"\"\"\n        if valid_df is None and isinstance(val_size, float) and isinstance(test_size, float):\n            assert 0 < val_size and val_size < 1\n            assert 0 < test_size and test_size < 1\n            train_df, valid_df = train_test_split(train_df, test_size=(val_size + test_size))\n\n        if test_df is None and isinstance(test_size, float):\n            assert 0 < test_size and test_size < 1\n            valid_df, test_df = train_test_split(valid_df, test_size=test_size)\n\n        datamodule = cls(\n            train_df=train_df,\n            target=target,\n            categorical_input=categorical_input,\n            numerical_input=numerical_input,\n            valid_df=valid_df,\n            test_df=test_df,\n            batch_size=batch_size,\n            num_workers=num_workers,\n        )\n        datamodule.data_pipeline = TabularDataPipeline(\n            categorical_input, numerical_input, target, datamodule.mean, datamodule.std, datamodule.codes\n        )\n\n        return datamodule\n\n    @classmethod\n    def from_csv(\n        cls,\n        train_csv: str,\n        target: str,\n        categorical_input: List,\n        numerical_input: List,\n        valid_csv: Optional[str] = None,\n        test_csv: Optional[str] = None,\n        batch_size: int = 8,\n        num_workers: Optional[int] = None,\n        val_size: Optional[float] = None,\n        test_size: Optional[float] = None,\n        **pandas_kwargs,\n    ):\n        \"\"\"Creates a TextClassificationData object from pandas DataFrames.\n\n        Args:\n            train_csv: train data csv file.\n            target: The column containing the class id.\n            categorical_input: The list of categorical columns.\n            numerical_input: The list of numerical columns.\n            valid_csv: validation data csv file.\n            test_csv: test data csv file.\n            batch_size: the batchsize to use for parallel loading. Defaults to 64.\n            num_workers: The number of workers to use for parallelized loading.\n                Defaults to None which equals the number of available CPU threads.\n            val_size: float between 0 and 1 to create a validation dataset from train dataset\n            test_size: float between 0 and 1 to create a test dataset from train validation\n\n        Returns:\n            TabularData: The constructed data module.\n\n        Examples::\n\n            text_data = TabularData.from_files(\"train.csv\", label_field=\"class\", text_field=\"sentence\")\n        \"\"\"\n        train_df = pd.read_csv(train_csv, **pandas_kwargs)\n        valid_df = pd.read_csv(valid_csv, **pandas_kwargs) if valid_csv is not None else None\n        test_df = pd.read_csv(test_csv, **pandas_kwargs) if test_csv is not None else None\n        datamodule = cls.from_df(\n            train_df, target, categorical_input, numerical_input, valid_df, test_df, batch_size, num_workers, val_size,\n            test_size\n        )\n        return datamodule\n\n    @property\n    def emb_sizes(self) -> list:\n        \"\"\"Recommended embedding sizes.\"\"\"\n\n        # https://developers.googleblog.com/2017/11/introducing-tensorflow-feature-columns.html\n        # The following \"formula\" provides a general rule of thumb about the number of embedding dimensions:\n        # embedding_dimensions =  number_of_categories**0.25\n\n        num_classes = [len(self.codes[cat]) for cat in self.cat_cols]\n        emb_dims = [max(int(n**0.25), 16) for n in num_classes]\n        return list(zip(num_classes, emb_dims))\n\n    @staticmethod\n    def default_pipeline() -> DataPipeline():\n        # TabularDataPipeline depends on the data\n        return DataPipeline()\n", "path": "flash/tabular/classification/data/data.py"}], "after_files": [{"content": "# Copyright The PyTorch Lightning team.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import Any, Dict, List, Optional\n\nimport numpy as np\nimport pandas as pd\nfrom pandas.core.frame import DataFrame\nfrom sklearn.model_selection import train_test_split\nfrom torch import Tensor\n\nfrom flash.core.classification import ClassificationDataPipeline\nfrom flash.core.data import DataPipeline\nfrom flash.core.data.datamodule import DataModule\nfrom flash.core.data.utils import _contains_any_tensor\nfrom flash.tabular.classification.data.dataset import (\n    _compute_normalization,\n    _dfs_to_samples,\n    _generate_codes,\n    _impute,\n    _pre_transform,\n    PandasDataset,\n)\n\n\nclass TabularDataPipeline(ClassificationDataPipeline):\n\n    def __init__(\n        self,\n        categorical_input: List,\n        numerical_input: List,\n        target: str,\n        mean: DataFrame,\n        std: DataFrame,\n        codes: Dict,\n    ):\n        self._categorical_input = categorical_input\n        self._numerical_input = numerical_input\n        self._target = target\n        self._mean = mean\n        self._std = std\n        self._codes = codes\n\n    def before_collate(self, samples: Any) -> Any:\n        \"\"\"Override to apply transformations to samples\"\"\"\n        if _contains_any_tensor(samples, dtype=(Tensor, np.ndarray)):\n            return samples\n        if isinstance(samples, str):\n            samples = pd.read_csv(samples)\n        if isinstance(samples, DataFrame):\n            samples = [samples]\n        dfs = _pre_transform(\n            samples, self._numerical_input, self._categorical_input, self._codes, self._mean, self._std\n        )\n        return _dfs_to_samples(dfs, self._categorical_input, self._numerical_input)\n\n\nclass TabularData(DataModule):\n    \"\"\"Data module for tabular tasks\"\"\"\n\n    def __init__(\n        self,\n        train_df: DataFrame,\n        target: str,\n        categorical_input: Optional[List] = None,\n        numerical_input: Optional[List] = None,\n        valid_df: Optional[DataFrame] = None,\n        test_df: Optional[DataFrame] = None,\n        batch_size: int = 2,\n        num_workers: Optional[int] = None,\n    ):\n        dfs = [train_df]\n        self._test_df = None\n\n        if categorical_input is None and numerical_input is None:\n            raise RuntimeError('Both `categorical_input` and `numerical_input` are None!')\n\n        categorical_input = categorical_input if categorical_input is not None else []\n        numerical_input = numerical_input if numerical_input is not None else []\n\n        if valid_df is not None:\n            dfs.append(valid_df)\n\n        if test_df is not None:\n            # save for predict function\n            self._test_df = test_df.copy()\n            self._test_df.drop(target, axis=1)\n            dfs.append(test_df)\n\n        # impute missing values\n        dfs = _impute(dfs, numerical_input)\n\n        # compute train dataset stats\n        self.mean, self.std = _compute_normalization(dfs[0], numerical_input)\n\n        if dfs[0][target].dtype == object:\n            # if the target is a category, not an int\n            self.target_codes = _generate_codes(dfs, [target])\n        else:\n            self.target_codes = None\n\n        self.codes = _generate_codes(dfs, categorical_input)\n\n        dfs = _pre_transform(\n            dfs, numerical_input, categorical_input, self.codes, self.mean, self.std, target, self.target_codes\n        )\n\n        # normalize\n        self.cat_cols = categorical_input\n        self.num_cols = numerical_input\n\n        self._num_classes = len(train_df[target].unique())\n\n        train_ds = PandasDataset(dfs[0], categorical_input, numerical_input, target)\n        valid_ds = PandasDataset(dfs[1], categorical_input, numerical_input, target) if valid_df is not None else None\n        test_ds = PandasDataset(dfs[-1], categorical_input, numerical_input, target) if test_df is not None else None\n        super().__init__(train_ds, valid_ds, test_ds, batch_size=batch_size, num_workers=num_workers)\n\n    @property\n    def num_classes(self) -> int:\n        return self._num_classes\n\n    @property\n    def num_features(self) -> int:\n        return len(self.cat_cols) + len(self.num_cols)\n\n    @classmethod\n    def from_df(\n        cls,\n        train_df: DataFrame,\n        target: str,\n        categorical_input: Optional[List] = None,\n        numerical_input: Optional[List] = None,\n        valid_df: Optional[DataFrame] = None,\n        test_df: Optional[DataFrame] = None,\n        batch_size: int = 8,\n        num_workers: Optional[int] = None,\n        val_size: float = None,\n        test_size: float = None,\n    ):\n        \"\"\"Creates a TabularData object from pandas DataFrames.\n\n        Args:\n            train_df: train data DataFrame\n            target: The column containing the class id.\n            categorical_input: The list of categorical columns.\n            numerical_input: The list of numerical columns.\n            valid_df: validation data DataFrame\n            test_df: test data DataFrame\n            batch_size: the batchsize to use for parallel loading. Defaults to 64.\n            num_workers: The number of workers to use for parallelized loading.\n                Defaults to None which equals the number of available CPU threads.\n            val_size: float between 0 and 1 to create a validation dataset from train dataset\n            test_size: float between 0 and 1 to create a test dataset from train validation\n\n        Returns:\n            TabularData: The constructed data module.\n\n        Examples::\n\n            text_data = TextClassificationData.from_files(\"train.csv\", label_field=\"class\", text_field=\"sentence\")\n        \"\"\"\n        if valid_df is None and isinstance(val_size, float) and isinstance(test_size, float):\n            assert 0 < val_size and val_size < 1\n            assert 0 < test_size and test_size < 1\n            train_df, valid_df = train_test_split(train_df, test_size=(val_size + test_size))\n\n        if test_df is None and isinstance(test_size, float):\n            assert 0 < test_size and test_size < 1\n            valid_df, test_df = train_test_split(valid_df, test_size=test_size)\n\n        datamodule = cls(\n            train_df=train_df,\n            target=target,\n            categorical_input=categorical_input,\n            numerical_input=numerical_input,\n            valid_df=valid_df,\n            test_df=test_df,\n            batch_size=batch_size,\n            num_workers=num_workers,\n        )\n        datamodule.data_pipeline = TabularDataPipeline(\n            categorical_input, numerical_input, target, datamodule.mean, datamodule.std, datamodule.codes\n        )\n\n        return datamodule\n\n    @classmethod\n    def from_csv(\n        cls,\n        train_csv: str,\n        target: str,\n        categorical_input: Optional[List] = None,\n        numerical_input: Optional[List] = None,\n        valid_csv: Optional[str] = None,\n        test_csv: Optional[str] = None,\n        batch_size: int = 8,\n        num_workers: Optional[int] = None,\n        val_size: Optional[float] = None,\n        test_size: Optional[float] = None,\n        **pandas_kwargs,\n    ):\n        \"\"\"Creates a TextClassificationData object from pandas DataFrames.\n\n        Args:\n            train_csv: train data csv file.\n            target: The column containing the class id.\n            categorical_input: The list of categorical columns.\n            numerical_input: The list of numerical columns.\n            valid_csv: validation data csv file.\n            test_csv: test data csv file.\n            batch_size: the batchsize to use for parallel loading. Defaults to 64.\n            num_workers: The number of workers to use for parallelized loading.\n                Defaults to None which equals the number of available CPU threads.\n            val_size: float between 0 and 1 to create a validation dataset from train dataset\n            test_size: float between 0 and 1 to create a test dataset from train validation\n\n        Returns:\n            TabularData: The constructed data module.\n\n        Examples::\n\n            text_data = TabularData.from_files(\"train.csv\", label_field=\"class\", text_field=\"sentence\")\n        \"\"\"\n        train_df = pd.read_csv(train_csv, **pandas_kwargs)\n        valid_df = pd.read_csv(valid_csv, **pandas_kwargs) if valid_csv is not None else None\n        test_df = pd.read_csv(test_csv, **pandas_kwargs) if test_csv is not None else None\n        datamodule = cls.from_df(\n            train_df, target, categorical_input, numerical_input, valid_df, test_df, batch_size, num_workers, val_size,\n            test_size\n        )\n        return datamodule\n\n    @property\n    def emb_sizes(self) -> list:\n        \"\"\"Recommended embedding sizes.\"\"\"\n\n        # https://developers.googleblog.com/2017/11/introducing-tensorflow-feature-columns.html\n        # The following \"formula\" provides a general rule of thumb about the number of embedding dimensions:\n        # embedding_dimensions =  number_of_categories**0.25\n\n        num_classes = [len(self.codes[cat]) for cat in self.cat_cols]\n        emb_dims = [max(int(n**0.25), 16) for n in num_classes]\n        return list(zip(num_classes, emb_dims))\n\n    @staticmethod\n    def default_pipeline() -> DataPipeline():\n        # TabularDataPipeline depends on the data\n        return DataPipeline()\n", "path": "flash/tabular/classification/data/data.py"}]}