class_docstr: MovieLens dataset for edge prediction tasks. The raw datasets are extracted from
  `MovieLens <https://grouplens.org/datasets/movielens/>`, introduced by
  `Movielens unplugged: experiences with an occasionally connected recommender system <https://dl.acm.org/doi/10.1145/604045.604094>`.
  
  The datasets consist of user ratings for movies and incorporate additional user/movie information in the form of features.
  The nodes represent users and movies, and the edges store ratings that users assign to movies.
  
  Statistics:
  
  MovieLens-100K (ml-100k)
  
  - Users: 943
  - Movies: 1,682
  - Ratings: 100,000 (1, 2, 3, 4, 5)
  
  MovieLens-1M (ml-1m)
  
  - Users: 6,040
  - Movies: 3,706
  - Ratings: 1,000,209 (1, 2, 3, 4, 5)
  
  MovieLens-10M (ml-10m)
  
  - Users: 69,878
  - Movies: 10,677
  - Ratings: 10,000,054 (0.5, 1, 1.5, ..., 4.5, 5.0)
  
  Parameters
  ----------
  name: str
      Dataset name. (:obj:`"ml-100k"`, :obj:`"ml-1m"`, :obj:`"ml-10m"`).
  valid_ratio: int
      Ratio of validation samples out of the whole dataset. Should be in (0.0, 1.0).
  test_ratio: int, optional
      Ratio of testing samples out of the whole dataset. Should be in (0.0, 1.0). And its sum with
      :obj:`valid_ratio` should be in (0.0, 1.0) as well. This parameter is invalid
      when :obj:`name` is :obj:`"ml-100k"`, since its testing samples are pre-specified.
      Default: None
  raw_dir : str, optional
      Raw file directory to download/store the data.
      Default: ~/.dgl/
  force_reload : bool, optional
      Whether to re-download(if the dataset has not been downloaded) and re-process the dataset.
      Default: False
  verbose : bool, optional
      Whether to print progress information. Default: True.
  transform : callable, optional
      A transform that takes in a :class:`~dgl.DGLGraph` object and returns
      a transformed version. The :class:`~dgl.DGLGraph` object will be
      transformed before every access.
  random_state : int, optional
      Random seed used for random dataset split. Default: 0
  
  Notes
  -----
  - When :obj:`name` is :obj:`"ml-100k"`, the :obj:`test_ratio` is invalid, and the training ratio is equal to 1-:obj:`valid_ratio`.
  When :obj:`name` is :obj:`"ml-1m"` or :obj:`"ml-10m"`, the :obj:`test_ratio` is valid,
  and the training ratio is equal to 1-:obj:`valid_ratio`-:obj:`test_ratio`.
  - The number of edges is doubled to form an undirected(bidirected) graph structure.
  
  Examples
  --------
  >>> from dgl.data import MovieLensDataset
  >>> dataset = MovieLensDataset(name='ml-100k', valid_ratio=0.2)
  >>> g = dataset[0]
  >>> g
  Graph(num_nodes={'movie': 1682, 'user': 943},
        num_edges={('movie', 'movie-user', 'user'): 100000, ('user', 'user-movie', 'movie'): 100000},
        metagraph=[('movie', 'user', 'movie-user'), ('user', 'movie', 'user-movie')])
  
  >>> # get ratings of edges in the training graph.
  >>> rate = g.edges['user-movie'].data['rate'] # or rate = g.edges['movie-user'].data['rate']
  >>> rate
  tensor([5., 5., 3.,  ..., 3., 3., 5.])
  
  >>> # get train, valid and test mask of edges
  >>> train_mask = g.edges['user-movie'].data['train_mask']
  >>> valid_mask = g.edges['user-movie'].data['valid_mask']
  >>> test_mask = g.edges['user-movie'].data['test_mask']
  
  >>> # get train, valid and test ratings
  >>> train_ratings = rate[train_mask]
  >>> valid_ratings = rate[valid_mask]
  >>> test_ratings = rate[test_mask]
  
  >>> # get input features of users
  >>> g.nodes["user"].data["feat"] # or g.nodes["movie"].data["feat"] for movie nodes
  tensor([[0.4800, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],
          [1.0600, 1.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],
          [0.4600, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],
          ...,
          [0.4000, 0.0000, 1.0000,  ..., 0.0000, 0.0000, 0.0000],
          [0.9600, 1.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],
          [0.4400, 0.0000, 1.0000,  ..., 0.0000, 0.0000, 0.0000]])
code: def process(self):
      print(f"Starting processing {self.name} ...")
  
      # 0. loading movie features
      movie_feat = load_info(
          os.path.join(self.raw_path, "movie_feat.pkl")
      ).to(torch.float)
      # 1. dataset split: train + (valid + ) test
      if self.name == "ml-100k":
          train_rating_data = self._load_raw_rates(
              os.path.join(self.raw_path, "u1.base"), "\t"
          )
          test_rating_data = self._load_raw_rates(
              os.path.join(self.raw_path, "u1.test"), "\t"
          )
          indices = np.arange(len(train_rating_data))
          train, valid, _ = split_dataset(
              indices,
              [1 - self.valid_ratio, self.valid_ratio, 0.0],
              shuffle=True,
              random_state=self.random_state,
          )
          train_rating_data, valid_rating_data = (
              train_rating_data.iloc[train.indices],
              train_rating_data.iloc[valid.indices],
          )
          all_rating_data = pd.concat(
              [train_rating_data, valid_rating_data, test_rating_data]
          )
  
      elif self.name == "ml-1m" or self.name == "ml-10m":
          all_rating_data = self._load_raw_rates(
              os.path.join(self.raw_path, "ratings.dat"), "::"
          )
          indices = np.arange(len(all_rating_data))
          train, valid, test = split_dataset(
              indices,
              [
                  1 - self.valid_ratio - self.test_ratio,
                  self.valid_ratio,
                  self.test_ratio,
              ],
              shuffle=True,
              random_state=self.random_state,
          )
          train_rating_data, valid_rating_data, test_rating_data = (
              all_rating_data.iloc[train.indices],
              all_rating_data.iloc[valid.indices],
              all_rating_data.iloc[test.indices],
          )
  
      # 2. load user and movie data, and drop those unseen in rating_data
      user_data = self._load_raw_user_data()
      movie_data = self._load_raw_movie_data()
      user_data = self._drop_unseen_nodes(
          data_df=user_data,
          col_name="id",
          reserved_ids_set=set(all_rating_data["user_id"].values),
      )
      movie_data = self._drop_unseen_nodes(
          data_df=movie_data,
          col_name="id",
          reserved_ids_set=set(all_rating_data["movie_id"].values),
      )
  
      user_feat = Tensor(self._process_user_feat(user_data))
  
      # 3. generate rating pairs
      # Map user/movie to the global id
      self._global_user_id_map = {
          ele: i for i, ele in enumerate(user_data["id"])
      }
      self._global_movie_id_map = {
          ele: i for i, ele in enumerate(movie_data["id"])
      }
  
      # pair value is idx rather than id
      u_indices, v_indices, labels = self._generate_pair_value(
          all_rating_data
      )
      all_rating_pairs = (
          LongTensor(u_indices),
          LongTensor(v_indices),
      )
      all_rating_values = Tensor(labels)
  
      graph = self.construct_g(
          all_rating_pairs, all_rating_values, user_feat, movie_feat
      )
      self.graph = self.add_masks(
          graph, train_rating_data, valid_rating_data, test_rating_data
      )
  
      print(f"End processing {self.name} ...")
  
imports: import os
  import numpy
  import pandas
  from torch import LongTensor, Tensor
  from ..base import dgl_warning
  from ..convert import heterograph
  from .dgl_dataset import DGLDataset
  from .utils import _get_dgl_url, download, extract_archive, load_graphs, load_info, save_graphs, save_info, split_dataset
label_desc: Use image node_id 4 for calling the MovieLensDataset obj's underlying member method code with example usage: obj.process() without return types