import matplotlib
if not hasattr(matplotlib.RcParams, "_get"):
    matplotlib.RcParams._get = dict.get

Modul 4: Teori#

Pyodide-bemærkning (Python direkte i Browseren)#

Koden i denne Notebook er beregnet til at blive kørt lokalt på din egen computer og ikke direkte i browseren via Pyodide. Årsagen er, at vi bruger scikit-learn til at downloade hele MNIST-datasættet. Dette er en data-tung operation, som involverer download af en stor fil, hvilket ikke umiddelbart understøttes eller er praktisk i et browser-baseret miljø som Pyodide.

Digitale billeder#

import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import fetch_openml
# Hent MNIST (784 = 28x28 pixels)
mnist = fetch_openml('mnist_784', version=1, as_frame=False)
X, y = mnist.data, mnist.target.astype('int64')
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Cell In[1], line 5
      1 import matplotlib.pyplot as plt
      2 import numpy as np
      3 from sklearn.datasets import fetch_openml
      4 # Hent MNIST (784 = 28x28 pixels)
----> 5 mnist = fetch_openml('mnist_784', version=1, as_frame=False)
      6 X, y = mnist.data, mnist.target.astype('int64')

File /usr/local/lib/python3.11/site-packages/sklearn/utils/_param_validation.py:218, in validate_params.<locals>.decorator.<locals>.wrapper(*args, **kwargs)
    212 try:
    213     with config_context(
    214         skip_parameter_validation=(
    215             prefer_skip_nested_validation or global_skip_validation
    216         )
    217     ):
--> 218         return func(*args, **kwargs)
    219 except InvalidParameterError as e:
    220     # When the function is just a wrapper around an estimator, we allow
    221     # the function to delegate validation to the estimator, but we replace
    222     # the name of the estimator by the name of the function in the error
    223     # message to avoid confusion.
    224     msg = re.sub(
    225         r"parameter of \w+ must be",
    226         f"parameter of {func.__qualname__} must be",
    227         str(e),
    228     )

File /usr/local/lib/python3.11/site-packages/sklearn/datasets/_openml.py:1135, in fetch_openml(name, version, data_id, data_home, target_column, cache, return_X_y, as_frame, n_retries, delay, parser, read_csv_kwargs)
   1133 # obtain the data
   1134 url = data_description["url"]
-> 1135 bunch = _download_data_to_bunch(
   1136     url,
   1137     return_sparse,
   1138     data_home,
   1139     as_frame=bool(as_frame),
   1140     openml_columns_info=features_list,
   1141     shape=shape,
   1142     target_columns=target_columns,
   1143     data_columns=data_columns,
   1144     md5_checksum=data_description["md5_checksum"],
   1145     n_retries=n_retries,
   1146     delay=delay,
   1147     parser=parser_,
   1148     read_csv_kwargs=read_csv_kwargs,
   1149 )
   1151 if return_X_y:
   1152     return bunch.data, bunch.target

File /usr/local/lib/python3.11/site-packages/sklearn/datasets/_openml.py:689, in _download_data_to_bunch(url, sparse, data_home, as_frame, openml_columns_info, data_columns, target_columns, shape, md5_checksum, n_retries, delay, parser, read_csv_kwargs)
    685     from pandas.errors import ParserError
    687     no_retry_exception = ParserError
--> 689 X, y, frame, categories = _retry_with_clean_cache(
    690     url, data_home, no_retry_exception
    691 )(_load_arff_response)(
    692     url,
    693     data_home,
    694     parser=parser,
    695     output_type=output_type,
    696     openml_columns_info=features_dict,
    697     feature_names_to_select=data_columns,
    698     target_names_to_select=target_columns,
    699     shape=shape,
    700     md5_checksum=md5_checksum,
    701     n_retries=n_retries,
    702     delay=delay,
    703     read_csv_kwargs=read_csv_kwargs,
    704 )
    706 return Bunch(
    707     data=X,
    708     target=y,
   (...)    712     target_names=target_columns,
    713 )

File /usr/local/lib/python3.11/site-packages/sklearn/datasets/_openml.py:66, in _retry_with_clean_cache.<locals>.decorator.<locals>.wrapper(*args, **kw)
     64     return f(*args, **kw)
     65 try:
---> 66     return f(*args, **kw)
     67 except URLError:
     68     raise

File /usr/local/lib/python3.11/site-packages/sklearn/datasets/_openml.py:554, in _load_arff_response(url, data_home, parser, output_type, openml_columns_info, feature_names_to_select, target_names_to_select, shape, md5_checksum, n_retries, delay, read_csv_kwargs)
    544 arff_params: Dict = dict(
    545     parser=parser,
    546     output_type=output_type,
   (...)    551     read_csv_kwargs=read_csv_kwargs or {},
    552 )
    553 try:
--> 554     X, y, frame, categories = _open_url_and_load_gzip_file(
    555         url, data_home, n_retries, delay, arff_params
    556     )
    557 except Exception as exc:
    558     if parser != "pandas":

File /usr/local/lib/python3.11/site-packages/sklearn/datasets/_openml.py:542, in _load_arff_response.<locals>._open_url_and_load_gzip_file(url, data_home, n_retries, delay, arff_params)
    540 gzip_file = _open_openml_url(url, data_home, n_retries=n_retries, delay=delay)
    541 with closing(gzip_file):
--> 542     return load_arff_from_gzip_file(gzip_file, **arff_params)

File /usr/local/lib/python3.11/site-packages/sklearn/datasets/_arff_parser.py:533, in load_arff_from_gzip_file(gzip_file, parser, output_type, openml_columns_info, feature_names_to_select, target_names_to_select, shape, read_csv_kwargs)
    524     return _liac_arff_parser(
    525         gzip_file,
    526         output_type,
   (...)    530         shape,
    531     )
    532 elif parser == "pandas":
--> 533     return _pandas_arff_parser(
    534         gzip_file,
    535         output_type,
    536         openml_columns_info,
    537         feature_names_to_select,
    538         target_names_to_select,
    539         read_csv_kwargs,
    540     )
    541 else:
    542     raise ValueError(
    543         f"Unknown parser: '{parser}'. Should be 'liac-arff' or 'pandas'."
    544     )

File /usr/local/lib/python3.11/site-packages/sklearn/datasets/_arff_parser.py:404, in _pandas_arff_parser(gzip_file, output_arrays_type, openml_columns_info, feature_names_to_select, target_names_to_select, read_csv_kwargs)
    392 default_read_csv_kwargs = {
    393     "header": None,
    394     "index_col": False,  # always force pandas to not use the first column as index
   (...)    401     "dtype": dtypes_positional,
    402 }
    403 read_csv_kwargs = {**default_read_csv_kwargs, **(read_csv_kwargs or {})}
--> 404 frame = pd.read_csv(gzip_file, **read_csv_kwargs)
    405 try:
    406     # Setting the columns while reading the file will select the N first columns
    407     # and not raise a ParserError. Instead, we set the columns after reading the
    408     # file and raise a ParserError if the number of columns does not match the
    409     # number of columns in the metadata given by OpenML.
    410     frame.columns = [name for name in openml_columns_info]

File /usr/local/lib/python3.11/site-packages/pandas/io/parsers/readers.py:873, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, skip_blank_lines, parse_dates, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, low_memory, memory_map, float_precision, storage_options, dtype_backend)
    861 kwds_defaults = _refine_defaults_read(
    862     dialect,
    863     delimiter,
   (...)    869     dtype_backend=dtype_backend,
    870 )
    871 kwds.update(kwds_defaults)
--> 873 return _read(filepath_or_buffer, kwds)

File /usr/local/lib/python3.11/site-packages/pandas/io/parsers/readers.py:306, in _read(filepath_or_buffer, kwds)
    303     return parser
    305 with parser:
--> 306     return parser.read(nrows)

File /usr/local/lib/python3.11/site-packages/pandas/io/parsers/readers.py:1947, in TextFileReader.read(self, nrows)
   1940 nrows = validate_integer("nrows", nrows)
   1941 try:
   1942     # error: "ParserBase" has no attribute "read"
   1943     (
   1944         index,
   1945         columns,
   1946         col_dict,
-> 1947     ) = self._engine.read(  # type: ignore[attr-defined]
   1948         nrows
   1949     )
   1950 except Exception:
   1951     self.close()

File /usr/local/lib/python3.11/site-packages/pandas/io/parsers/c_parser_wrapper.py:215, in CParserWrapper.read(self, nrows)
    213 try:
    214     if self.low_memory:
--> 215         chunks = self._reader.read_low_memory(nrows)
    216         # destructive to chunks
    217         data = _concatenate_chunks(chunks, self.names)

File pandas/_libs/parsers.pyx:832, in pandas._libs.parsers.TextReader.read_low_memory()
--> 832 'Could not get source, probably due dynamically evaluated source code.'

File pandas/_libs/parsers.pyx:911, in pandas._libs.parsers.TextReader._read_rows()
--> 911 'Could not get source, probably due dynamically evaluated source code.'

File pandas/_libs/parsers.pyx:1009, in pandas._libs.parsers.TextReader._convert_column_data()
-> 1009 'Could not get source, probably due dynamically evaluated source code.'

File pandas/_libs/parsers.pyx:1048, in pandas._libs.parsers.TextReader._convert_tokens()
-> 1048 'Could not get source, probably due dynamically evaluated source code.'

File pandas/_libs/parsers.pyx:1145, in pandas._libs.parsers.TextReader._convert_with_dtype()
-> 1145 'Could not get source, probably due dynamically evaluated source code.'

File /usr/local/lib/python3.11/site-packages/pandas/core/dtypes/dtypes.py:531, in CategoricalDtype.construct_array_type(self)
    528     combined_hashed = combine_hash_arrays(iter(cat_array), num_items=len(cat_array))
    529     return np.bitwise_xor.reduce(combined_hashed)
--> 531 def construct_array_type(self) -> type_t[Categorical]:
    532     """
    533     Return the array type associated with this dtype.
    534 
   (...)    537     type
    538     """
    539     from pandas import Categorical

KeyboardInterrupt: 
plt.figure(figsize=(12, 12))
plt.subplot(221)
plt.imshow(X[0].reshape(28, 28), cmap='gray')
plt.title(f"Digit: {y[0]}")
plt.subplot(222)
plt.imshow(X[1].reshape(28, 28), cmap='gray')
plt.title(f"Digit: {y[1]}")
plt.subplot(223)
plt.imshow(X[2].reshape(28, 28), cmap='gray')
plt.title(f"Digit: {y[2]}")
plt.subplot(224)
plt.imshow(X[3].reshape(28, 28), cmap='gray')
plt.title(f"Digit: {y[3]}")
# vis grafen
plt.show()
../../../_images/ac02fd017c9301142d38e29d1d91bbb2d24e984048a5cad24e53b288d6b70eca.png

Vektorfunktioner#

Lad \(d,k \in \mathbb{N}\). En vektorfunktion af flere variable er en funktion af formen

\[\begin{equation*} \pmb{f} \colon \operatorname{dom}(\pmb{f}) \to \mathbb{R}^k, \text{\; hvor }\operatorname{dom}(\pmb{f}) \subseteq \mathbb{R}^d. \end{equation*}\]

Altså har en vektorfunktion \(\pmb{f} = \pmb{x} \mapsto \pmb{f}(\pmb{x})\):

  • Input (domænet): vektorer \(\pmb{x}\) i \(\mathbb{R}^d\)

  • Output (kodomænet): vektorer \(\pmb{f}(\pmb{x})\) i \(\mathbb{R}^k\)

Input \(\pmb{x}_0\)#

# Vis det tredje billede fra træningssættet
x0 = X[2].reshape(28, 28)
plt.figure(figsize=(7, 7))
plt.imshow(x0, cmap='gray')
plt.axis('off')
plt.show()
../../../_images/390a1144d8425fb8df6492be504436a7343a1f66372d758a9254ada53d031a2c.png

Output \(\pmb{f}(\pmb{x}_0)\)#

  • Output:

"Dette er cifret 4"


  • Ideelt output:

\[\begin{equation*} \pmb{f}(\pmb{x}_0) = \begin{bmatrix} 0 \\ 0 \\ 0 \\ 0 \\ 1 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \end{bmatrix} \end{equation*}\]

Dette betyder: "100% sikker på, at dette er cifret 4"


  • Mere realistisk output:

\[\begin{equation*} \pmb{f}(\pmb{x}_0) = \begin{bmatrix} 0.01 \\ 0.03 \\ 0.01 \\ 0.01 \\ 0.87 \\ 0.01 \\ 0.01 \\ 0.03 \\ 0.01 \\ 0.01 \end{bmatrix} \end{equation*}\]

Dette betyder: "87% sikker på, at dette er cifret 4. Lille sandsynlighed (3%) for, at det er 1 eller 7."


  • Under alle omstændigheder: Outputtet er en vektor af sandsynligheder i \(\mathbb{R}^{10}\). Derfor er \(\operatorname{co\text{-}dom}(\pmb{f})=\mathbb{R}^{10}\).

Hvad med inputtet?#

Det er faktisk en matrix på størrelse 28x28:

\[\begin{split} %\tiny \scriptsize \begin{bmatrix} 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 67 & 232 & 39 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 62 & 81 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 120 & 180 & 39 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 126 & 163 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 2 & 153 & 210 & 40 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 220 & 163 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 27 & 254 & 162 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 222 & 163 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 183 & 254 & 125 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 46 & 245 & 163 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 198 & 254 & 56 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 120 & 254 & 163 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 23 & 231 & 254 & 29 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 159 & 254 & 120 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 163 & 254 & 216 & 16 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 159 & 254 & 67 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 14 & 86 & 178 & 248 & 254 & 91 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 159 & 254 & 85 & 0 & 0 & 0 & 47 & 49 & 116 & 144 & 150 & 241 & 243 & 234 & 179 & 241 & 252 & 40 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 150 & 253 & 237 & 207 & 207 & 207 & 253 & 254 & 250 & 240 & 198 & 143 & 91 & 28 & 5 & 233 & 250 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 119 & 177 & 177 & 177 & 177 & 177 & 98 & 56 & 0 & 0 & 0 & 0 & 0 & 102 & 254 & 220 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 169 & 254 & 137 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 169 & 254 & 57 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 169 & 254 & 57 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 169 & 255 & 94 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 169 & 254 & 96 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 169 & 254 & 153 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 169 & 255 & 153 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 96 & 254 & 153 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \end{bmatrix} \end{split}\]

Men det er ikke umiddelbart en (søjle)vektor!

Vi kan gøre den om til en vektor ved at stakke billedets rækker oven på hinanden. Dette kaldes flattening (udfladning) af billedet i Python.

# Udskriv som søjle med 784 tal
print("\nSøjle-repræsentation af billedet (784 tal):")
x0.reshape(784,1)
Søjle-repræsentation af billedet (784 tal):
array([[  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [ 67],
       [232],
       [ 39],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [ 62],
       [ 81],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [120],
       [180],
       [ 39],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [126],
       [163],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  2],
       [153],
       [210],
       [ 40],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [220],
       [163],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [ 27],
       [254],
       [162],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [222],
       [163],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [183],
       [254],
       [125],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [ 46],
       [245],
       [163],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [198],
       [254],
       [ 56],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [120],
       [254],
       [163],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [ 23],
       [231],
       [254],
       [ 29],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [159],
       [254],
       [120],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [163],
       [254],
       [216],
       [ 16],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [159],
       [254],
       [ 67],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [ 14],
       [ 86],
       [178],
       [248],
       [254],
       [ 91],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [159],
       [254],
       [ 85],
       [  0],
       [  0],
       [  0],
       [ 47],
       [ 49],
       [116],
       [144],
       [150],
       [241],
       [243],
       [234],
       [179],
       [241],
       [252],
       [ 40],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [150],
       [253],
       [237],
       [207],
       [207],
       [207],
       [253],
       [254],
       [250],
       [240],
       [198],
       [143],
       [ 91],
       [ 28],
       [  5],
       [233],
       [250],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [119],
       [177],
       [177],
       [177],
       [177],
       [177],
       [ 98],
       [ 56],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [102],
       [254],
       [220],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [169],
       [254],
       [137],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [169],
       [254],
       [ 57],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [169],
       [254],
       [ 57],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [169],
       [255],
       [ 94],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [169],
       [254],
       [ 96],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [169],
       [254],
       [153],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [169],
       [255],
       [153],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [ 96],
       [254],
       [153],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0],
       [  0]])

Så vi kan tænke på inputtet som vektorer i \(\mathbb{R}^{784}\)! Det vil sige

En AI funktion#

AI’en er en vektorfunktion med \(d=784\), \(k=10\).

I maskinlæring kaldes funktionen for en model, og den specifikke AI-funktion afhænger typisk af tusindvis eller millioner af parametre (kaldet vægte). For hvert sæt af parametre/vægte får vi en ny AI-funktion. Sådanne funktioner (også dybe neurale netværk) er ikke særligt komplicerede, men ofte lange at skrive eksplicit. De er bygget af

  • Sammensætning af simple vektorfunktioner \(\pmb{g} \circ \pmb{h}\)

  • De simple funktioner er normalt kun: 1. Affine vektorfunktioner \(\pmb{x} \mapsto A \pmb{x} + \pmb{b}\) (elementerne i matrixen \(A\) og vektoren \(\pmb{b}\) er parametrene/vægtene) 2. En ikke-lineær aktiveringsfunktion, fx ReLU.

Antallet af sammensætninger \(\pmb{g}_1 \circ \pmb{g}_2 \circ \pmb{g}_3 \circ \cdots \circ \pmb{g}_N\) beskriver netværkets dybde.

Neurale netværk#

Hvordan ser disse “AI-funktioner” ud?

Generel notation for et feedforward ReLU-netværk#

Et feedforward-netværk beregner outputtet ved sekventielt at føre input gennem en række lag. For hvert lag \(\ell\) beregnes først en pre-aktivering (også kaldet logits), \(z^{(\ell)}\), efterfulgt af en aktivering (eller hidden state), \(h^{(\ell)}\).

\[\begin{equation*} \begin{aligned} &h^{(0)} = x \in \mathbb{R}^{n_0} &&\text{(Input)}\\ &z^{(\ell)} = W_\ell h^{(\ell-1)} + b_\ell, && \ell = 1,2,\dots,L &&\text{(Logits)}\\ &h^{(\ell)} = \begin{cases} \sigma (z^{(\ell)}), & \ell < L, \\ z^{(\ell)}, & \ell = L, \end{cases} &&\text{(Activation)} \end{aligned} \end{equation*}\]

hvor

  • \(h^{(0)}\) er input-vektoren \(x\).

  • \(W_\ell \in \mathbb{R}^{n_\ell \times n_{\ell-1}}\) er vægtmatricen for lag \(\ell\).

  • \(b_\ell \in \mathbb{R}^{n_\ell}\) er bias-vektoren.

  • \(\sigma:\mathbb{R}\to\mathbb{R}\) er en ikke-lineær aktiveringsfunktion (anvendt koordinatvis) typisk ReLU:

\[\begin{equation*} \sigma(z) = \max(0,z) \quad\text{(ReLU)} \end{equation*}\]
  • \(n_0=d\) er inputdimensionen, \(n_L=k\) outputdimensionen.

Vi siger kort at netværket er af formen \(n_0 \to n_1 \to \cdots \to n_L\).

Netværkets samlede funktion \(\Phi: \mathbb{R}^d \to \mathbb{R}^k\) giver det endelige output:

\[\begin{equation*} \Phi(x) = z^{(L)} = W_L h^{(L-1)} + b_L, \end{equation*}\]

idet sidste lag her er lineært (uden ReLU-aktivering).

Et neuralt netværk

Shallow netværk (ét skjult lag med L=2)#

For et shallow netværk \(\Phi:\mathbb{R}^2\to\mathbb{R}\) med ét skjult lag af størrelse \(n\):

\[\begin{equation*} \Phi(x) = W_2 \, \sigma(W_1 x + b_1) + b_2, \end{equation*}\]

hvor

  • \(x \in \mathbb{R}^2\),

  • \(W_1 \in \mathbb{R}^{n\times 2},\ b_1 \in \mathbb{R}^{n},\)

  • \(W_2 \in \mathbb{R}^{1\times n},\ b_2 \in \mathbb{R}.\)

Illustration af lagene:

\[\begin{equation*} h^{(0)} \xrightarrow{W_1,b_1} z^{(1)} \xrightarrow{\sigma} h^{(1)} \xrightarrow{W_2,b_2} z^{(2)} \xrightarrow{\sigma} h^{(2)} \xrightarrow{W_3,b_3} z^{(3)} = \Phi(x) \end{equation*}\]

Hvert ReLU-lag opdeler rummet i lineære regioner bestemt af ligningerne \( (W_\ell h^{(\ell-1)} + b_\ell)_i = 0 \), så \(\Phi\) er en stykkevist lineær funktion\(\mathbb{R}^d\).

Generel formel for et ReLU-netværk med \(L=3\)#

Vi betragter en funktion

\[\begin{equation*} \Phi:\mathbb{R}^{n_0}\to\mathbb{R}^{n_3} \end{equation*}\]

defineret som et fuldt forbundet netværk med to skjulte lag:

\[\begin{equation*} \begin{aligned} h^{(0)} &= x \in \mathbb{R}^{n_0}, \\[2pt] z^{(1)} &= W_1 h^{(0)} + b_1,\\ h^{(1)} &= \sigma \bigl(z^{(1)}\bigr), \\[4pt] z^{(2)} &= W_2 h^{(1)} + b_2,\\ h^{(2)} &= \sigma \bigl(z^{(2)}\bigr), \\[4pt] z^{(3)} &= W_3 h^{(2)} + b_3,\\ h^{(3)} &= z^{(3)}. \end{aligned} \end{equation*}\]

hvor \(n_0 = d\), \(n_3 = k\), og

  • \(W_1 \in \mathbb{R}^{n_1\times n_0},\ b_1\in\mathbb{R}^{n_1}\)

  • \(W_2 \in \mathbb{R}^{n_2\times n_1},\ b_2\in\mathbb{R}^{n_2}\)

  • \(W_3 \in \mathbb{R}^{n_3\times n_2},\ b_3\in\mathbb{R}^{n_3}\)

Det samlede funktionsudtryk bliver:

\[\begin{equation*} \Phi(x) = W_3 \, \sigma \bigl(W_2 \, \sigma(W_1 x + b_1) + b_2 \bigr) + b_3. \end{equation*}\]

Eksempel: For et konkret netværk med to inputvariabler og ét output af formen \(2 \to n_1 \to n_2 \to 1\):

\[\begin{equation*} \Phi(x_1,x_2) = W_3 \,\sigma \Big(W_2 \, \sigma \big(W_1 \begin{bmatrix}x_1 \\ x_2\end{bmatrix} + b_1\big) + b_2\Big) + b_3, \end{equation*}\]

hvor dimensionerne er

\[\begin{equation*} W_1 \in \mathbb{R}^{n_1\times2},\quad W_2 \in \mathbb{R}^{n_2\times n_1},\quad W_3 \in \mathbb{R}^{1\times n_2}. \end{equation*}\]

Netværk og træning direkte i SKLearn#

Vi skal finde en “AI-funktion”

\[\begin{equation*} \Phi : \mathbb{R}^{784} \to \mathbb{R}^{10} \end{equation*}\]

der “bedst”-muligt kan klassificere et billede af et håndskrevet ciffer.

I koden nedenfor opbygges denne som et ReLU-netværk med to skjulte lag, hvilket giver en samlet dybde på \(L=3\). Formen af netværket er \(784 \to 256 \to 128 \to 10\). Altså er vægt-matricerne af størrelse

\[\begin{equation*} \begin{aligned} &W_1 \in \mathbb{R}^{256 \times 784}, \quad b_1 \in \mathbb{R}^{256}, \\ &W_2 \in \mathbb{R}^{128 \times 256}, \quad b_2 \in \mathbb{R}^{128}, \\ &W_3 \in \mathbb{R}^{10 \times 128}, \quad b_3 \in \mathbb{R}^{10}. \end{aligned} \end{equation*}\]
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier

# Normaliser til [0,1]
X = X / 255.0

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=1/7, random_state=42
)

# DNN med samme “størrelse” som PyTorch-eksemplet
clf = MLPClassifier(
    hidden_layer_sizes=(256, 128),  # to skjulte lag
    activation='relu',
    solver='adam',
    batch_size=64,
    learning_rate_init=1e-3,
    max_iter=6,
    verbose=True
)

Netværkets størrelse#

Hvor mange parametre er der?

Svar#

Det samlede antal parametre for netværket er:

  • Lag 1: (784 input × 256 neuroner) + 256 bias = 200.704 + 256 = 200.960

  • Lag 2: (256 input × 128 neuroner) + 128 bias = 32.768 + 128 = 32.896

  • Lag 3: (128 input × 10 neuroner) + 10 bias = 1.280 + 10 = 1.290

I alt: 200.960 + 32.896 + 1.290 = 235.146

Træning via SKLearn#

Vi finder de optimale værdier for alle parametrene i \(Phi-\)funktionen ved at træne modellen med fit-metoden:

# Træn
clf.fit(X_train, y_train)
Iteration 1, loss = 0.22757620
Iteration 2, loss = 0.08920455
Iteration 3, loss = 0.05955793
Iteration 4, loss = 0.04347159
Iteration 5, loss = 0.03397271
Iteration 6, loss = 0.02918372
/home/jakle/Python/envs/intermat/lib/python3.10/site-packages/sklearn/neural_network/_multilayer_perceptron.py:781: ConvergenceWarning: Stochastic Optimizer: Maximum iterations (6) reached and the optimization hasn't converged yet.
  warnings.warn(
MLPClassifier(batch_size=64, hidden_layer_sizes=(256, 128), max_iter=6,
              verbose=True)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.

Forudsigelse på et enkelt billede#

Denne funktion kan vi nu bruge på et enkelt input-billede for at få en forudsigelse. Lad os tage et enkelt billede fra vores testsæt og se, hvad modellen forudsiger.

image_index = 2 # Vælg et billede (input)
input_image = X_test[image_index:image_index+1] # Format (1, 784)
true_label = y_test[image_index]

probability_vector = clf.predict_proba(input_image) # Få sandsynlighedsvektoren
predicted_label = clf.predict(input_image) # Lav forudsigelse 

print(input_image)
print(true_label)
print(probability_vector)
print(predicted_label)
[[0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.61960784 0.90588235 0.14901961 0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.02745098 0.25490196 0.56862745
  0.56862745 0.34509804 0.         0.05490196 0.83137255 0.99215686
  0.28235294 0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.09019608 0.14509804
  0.25882353 0.7254902  0.99215686 0.9372549  0.91372549 0.99215686
  0.59607843 0.45490196 0.99215686 0.80784314 0.10980392 0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.06666667 0.87058824 0.99215686 0.99215686 0.9372549
  0.80392157 0.27058824 0.14509804 0.64705882 0.99607843 0.99215686
  0.89803922 0.10980392 0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.0745098
  0.90196078 0.99215686 0.99215686 0.48235294 0.         0.
  0.         0.58823529 0.99607843 0.81176471 0.24313725 0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.14901961 0.60392157
  0.99215686 0.78823529 0.19215686 0.         0.46666667 0.98431373
  0.98431373 0.30588235 0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.03921569 0.76470588 0.99215686
  0.92941176 0.80784314 0.97647059 0.99215686 0.56470588 0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.10196078 0.50196078 0.92156863 0.99215686
  0.99215686 0.99215686 0.90196078 0.38431373 0.14509804 0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.38039216 0.99215686 0.99215686 0.99215686
  0.99607843 0.99215686 0.9372549  0.58431373 0.12156863 0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.56078431 0.99215686 0.78823529 0.06666667 0.29411765 0.51764706
  0.81176471 0.99215686 0.84705882 0.11372549 0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.1372549  0.90196078 0.99607843
  0.54509804 0.         0.         0.         0.07058824 0.56470588
  0.98431373 0.8627451  0.12156863 0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.80784314 0.99215686 0.09411765 0.
  0.         0.         0.         0.         0.66666667 0.99215686
  0.69019608 0.01568627 0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.50980392 0.99215686 0.38823529 0.         0.         0.
  0.         0.         0.09019608 0.78039216 0.99215686 0.14117647
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.27058824 0.96862745
  0.64705882 0.64313725 0.         0.         0.         0.
  0.         0.28627451 0.99215686 0.45882353 0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.85490196 0.99215686 0.99215686
  0.11764706 0.         0.         0.         0.         0.28627451
  0.99215686 0.61176471 0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.38431373 0.83137255 0.99215686 0.8745098  0.3254902
  0.         0.         0.         0.07058824 0.85098039 0.90588235
  0.07058824 0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.28627451 0.98039216 0.99607843 0.88627451 0.30980392 0.
  0.         0.23529412 0.95686275 0.86666667 0.0627451  0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.13333333
  0.99607843 0.99215686 0.83921569 0.30980392 0.         0.28627451
  0.99215686 0.43529412 0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.36470588 0.99215686
  0.99215686 0.97647059 0.78823529 0.81568627 0.99215686 0.14117647
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.00392157 0.31764706 0.81176471 0.99215686
  0.99215686 0.85490196 0.36078431 0.00784314 0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.        ]]
8
[[7.08580512e-05 2.61484819e-04 1.44964793e-05 1.17057312e-03
  1.67150883e-05 5.34671916e-02 4.29566890e-01 8.57747096e-06
  5.14443444e-01 9.79769433e-04]]
[8]

Total forudsigelse#

Den samlede procentandel af billeder i testsættet, som modellen klassificerede korrekt kan findes ved:

# Samlet evaluering
print("Test accuracy:", clf.score(X_test, y_test))
Test accuracy: 0.9778

Visualisering af forudsigelser#

For at få en bedre fornemmelse af, hvordan modellen opfører sig, kan vi visualisere dens forudsigelser på enkelte billeder fra testsættet. Nedenstående funktion plotter billedet, den korrekte label, den forudsagte label og et søjlediagram over de forudsagte sandsynligheder for hver klasse. Dette er nyttigt for at se, hvornår modellen er sikker, og hvornår den er i tvivl.

def show_images_with_mlp_probabilities(clf, X_test, y_test, X_test_orig, 
                                       num_images=5, only_incorrect=False,
                                       image_shape=(8,8)):
    # Predict full test set
    pred_labels = clf.predict(X_test)
    probas = clf.predict_proba(X_test)

    # Select indices
    all_indices = np.arange(len(X_test))
    if only_incorrect:
        indices = all_indices[pred_labels != y_test][:num_images]
    else:
        indices = all_indices[:num_images]

    plt.figure(figsize=(12, 6))

    for i, idx in enumerate(indices):
        # --- Image plot ---
        plt.subplot(2, num_images, i + 1)
        img = X_test_orig[idx].reshape(image_shape)
        plt.imshow(img, cmap='gray')
        plt.title(f"Idx {idx}\nTrue {y_test[idx]}\nPred {pred_labels[idx]}")
        plt.axis('off')

        # --- Probability distribution ---
        plt.subplot(2, num_images, num_images + i + 1)

        p = probas[idx]

        classes = np.arange(len(p))
        colors = [
            "red" if c == y_test[idx] else
            ("green" if c == pred_labels[idx] else "blue")
            for c in classes
        ]

        plt.bar(classes, p, color=colors)
        plt.xticks(classes)
        plt.ylim(0, 1)
        plt.xlabel("Class")
        plt.ylabel("Probability")

    plt.tight_layout()
    plt.show()

show_images_with_mlp_probabilities(
    clf, 
    X_test, 
    y_test, 
    X_test_orig=X_test, 
    only_incorrect=False,
    num_images=5,
    image_shape=(28,28)
)    
../../../_images/ccce3d5195a8015fc07e0e38c82611993e3d80123876949d3b9b4c4ddb86189c.png
show_images_with_mlp_probabilities(
    clf, 
    X_test, 
    y_test, 
    X_test_orig=X_test, 
    only_incorrect=True,
    num_images=5,
    image_shape=(28,28)
)    
../../../_images/dbc33ccc7294d608abd11b95bf450390e52c13b38ecd094453960a0bbef3e3c8.png