{
"cells": [
{
"cell_type": "markdown",
"id": "498d70fa",
"metadata": {},
"source": [
"# 线性回归(二)"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "226badd7",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"id": "70d2906a",
"metadata": {},
"source": [
"1) 使用pandas库的read_csv()函数(可以参考[pandas的官方文档](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html))将训练数据集'train.csv'和测试数据集'test.csv'载入到Dataframe对象中。"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "10b4e00e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[31mSignature:\u001b[39m\n",
"pd.read_csv(\n",
" filepath_or_buffer: \u001b[33m'FilePath | ReadCsvBuffer[bytes] | ReadCsvBuffer[str]'\u001b[39m,\n",
" *,\n",
" sep: \u001b[33m'str | None | lib.NoDefault'\u001b[39m = ,\n",
" delimiter: \u001b[33m'str | None | lib.NoDefault'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" header: \u001b[33m\"int | Sequence[int] | None | Literal['infer']\"\u001b[39m = \u001b[33m'infer'\u001b[39m,\n",
" names: \u001b[33m'Sequence[Hashable] | None | lib.NoDefault'\u001b[39m = ,\n",
" index_col: \u001b[33m'IndexLabel | Literal[False] | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" usecols: \u001b[33m'UsecolsArgType'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" dtype: \u001b[33m'DtypeArg | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" engine: \u001b[33m'CSVEngine | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" converters: \u001b[33m'Mapping[Hashable, Callable] | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" true_values: \u001b[33m'list | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" false_values: \u001b[33m'list | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" skipinitialspace: \u001b[33m'bool'\u001b[39m = \u001b[38;5;28;01mFalse\u001b[39;00m,\n",
" skiprows: \u001b[33m'list[int] | int | Callable[[Hashable], bool] | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" skipfooter: \u001b[33m'int'\u001b[39m = \u001b[32m0\u001b[39m,\n",
" nrows: \u001b[33m'int | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" na_values: \u001b[33m'Hashable | Iterable[Hashable] | Mapping[Hashable, Iterable[Hashable]] | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" keep_default_na: \u001b[33m'bool'\u001b[39m = \u001b[38;5;28;01mTrue\u001b[39;00m,\n",
" na_filter: \u001b[33m'bool'\u001b[39m = \u001b[38;5;28;01mTrue\u001b[39;00m,\n",
" verbose: \u001b[33m'bool | lib.NoDefault'\u001b[39m = ,\n",
" skip_blank_lines: \u001b[33m'bool'\u001b[39m = \u001b[38;5;28;01mTrue\u001b[39;00m,\n",
" parse_dates: \u001b[33m'bool | Sequence[Hashable] | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" infer_datetime_format: \u001b[33m'bool | lib.NoDefault'\u001b[39m = ,\n",
" keep_date_col: \u001b[33m'bool | lib.NoDefault'\u001b[39m = ,\n",
" date_parser: \u001b[33m'Callable | lib.NoDefault'\u001b[39m = ,\n",
" date_format: \u001b[33m'str | dict[Hashable, str] | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" dayfirst: \u001b[33m'bool'\u001b[39m = \u001b[38;5;28;01mFalse\u001b[39;00m,\n",
" cache_dates: \u001b[33m'bool'\u001b[39m = \u001b[38;5;28;01mTrue\u001b[39;00m,\n",
" iterator: \u001b[33m'bool'\u001b[39m = \u001b[38;5;28;01mFalse\u001b[39;00m,\n",
" chunksize: \u001b[33m'int | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" compression: \u001b[33m'CompressionOptions'\u001b[39m = \u001b[33m'infer'\u001b[39m,\n",
" thousands: \u001b[33m'str | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" decimal: \u001b[33m'str'\u001b[39m = \u001b[33m'.'\u001b[39m,\n",
" lineterminator: \u001b[33m'str | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" quotechar: \u001b[33m'str'\u001b[39m = \u001b[33m'\"'\u001b[39m,\n",
" quoting: \u001b[33m'int'\u001b[39m = \u001b[32m0\u001b[39m,\n",
" doublequote: \u001b[33m'bool'\u001b[39m = \u001b[38;5;28;01mTrue\u001b[39;00m,\n",
" escapechar: \u001b[33m'str | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" comment: \u001b[33m'str | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" encoding: \u001b[33m'str | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" encoding_errors: \u001b[33m'str | None'\u001b[39m = \u001b[33m'strict'\u001b[39m,\n",
" dialect: \u001b[33m'str | csv.Dialect | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" on_bad_lines: \u001b[33m'str'\u001b[39m = \u001b[33m'error'\u001b[39m,\n",
" delim_whitespace: \u001b[33m'bool | lib.NoDefault'\u001b[39m = ,\n",
" low_memory: \u001b[33m'bool'\u001b[39m = \u001b[38;5;28;01mTrue\u001b[39;00m,\n",
" memory_map: \u001b[33m'bool'\u001b[39m = \u001b[38;5;28;01mFalse\u001b[39;00m,\n",
" float_precision: \u001b[33m\"Literal['high', 'legacy'] | None\"\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" storage_options: \u001b[33m'StorageOptions | None'\u001b[39m = \u001b[38;5;28;01mNone\u001b[39;00m,\n",
" dtype_backend: \u001b[33m'DtypeBackend | lib.NoDefault'\u001b[39m = ,\n",
") -> \u001b[33m'DataFrame | TextFileReader'\u001b[39m\n",
"\u001b[31mDocstring:\u001b[39m\n",
"Read a comma-separated values (csv) file into DataFrame.\n",
"\n",
"Also supports optionally iterating or breaking of the file\n",
"into chunks.\n",
"\n",
"Additional help can be found in the online docs for\n",
"`IO Tools `_.\n",
"\n",
"Parameters\n",
"----------\n",
"filepath_or_buffer : str, path object or file-like object\n",
" Any valid string path is acceptable. The string could be a URL. Valid\n",
" URL schemes include http, ftp, s3, gs, and file. For file URLs, a host is\n",
" expected. A local file could be: file://localhost/path/to/table.csv.\n",
"\n",
" If you want to pass in a path object, pandas accepts any ``os.PathLike``.\n",
"\n",
" By file-like object, we refer to objects with a ``read()`` method, such as\n",
" a file handle (e.g. via builtin ``open`` function) or ``StringIO``.\n",
"sep : str, default ','\n",
" Character or regex pattern to treat as the delimiter. If ``sep=None``, the\n",
" C engine cannot automatically detect\n",
" the separator, but the Python parsing engine can, meaning the latter will\n",
" be used and automatically detect the separator from only the first valid\n",
" row of the file by Python's builtin sniffer tool, ``csv.Sniffer``.\n",
" In addition, separators longer than 1 character and different from\n",
" ``'\\s+'`` will be interpreted as regular expressions and will also force\n",
" the use of the Python parsing engine. Note that regex delimiters are prone\n",
" to ignoring quoted data. Regex example: ``'\\r\\t'``.\n",
"delimiter : str, optional\n",
" Alias for ``sep``.\n",
"header : int, Sequence of int, 'infer' or None, default 'infer'\n",
" Row number(s) containing column labels and marking the start of the\n",
" data (zero-indexed). Default behavior is to infer the column names: if no ``names``\n",
" are passed the behavior is identical to ``header=0`` and column\n",
" names are inferred from the first line of the file, if column\n",
" names are passed explicitly to ``names`` then the behavior is identical to\n",
" ``header=None``. Explicitly pass ``header=0`` to be able to\n",
" replace existing names. The header can be a list of integers that\n",
" specify row locations for a :class:`~pandas.MultiIndex` on the columns\n",
" e.g. ``[0, 1, 3]``. Intervening rows that are not specified will be\n",
" skipped (e.g. 2 in this example is skipped). Note that this\n",
" parameter ignores commented lines and empty lines if\n",
" ``skip_blank_lines=True``, so ``header=0`` denotes the first line of\n",
" data rather than the first line of the file.\n",
"names : Sequence of Hashable, optional\n",
" Sequence of column labels to apply. If the file contains a header row,\n",
" then you should explicitly pass ``header=0`` to override the column names.\n",
" Duplicates in this list are not allowed.\n",
"index_col : Hashable, Sequence of Hashable or False, optional\n",
" Column(s) to use as row label(s), denoted either by column labels or column\n",
" indices. If a sequence of labels or indices is given, :class:`~pandas.MultiIndex`\n",
" will be formed for the row labels.\n",
"\n",
" Note: ``index_col=False`` can be used to force pandas to *not* use the first\n",
" column as the index, e.g., when you have a malformed file with delimiters at\n",
" the end of each line.\n",
"usecols : Sequence of Hashable or Callable, optional\n",
" Subset of columns to select, denoted either by column labels or column indices.\n",
" If list-like, all elements must either\n",
" be positional (i.e. integer indices into the document columns) or strings\n",
" that correspond to column names provided either by the user in ``names`` or\n",
" inferred from the document header row(s). If ``names`` are given, the document\n",
" header row(s) are not taken into account. For example, a valid list-like\n",
" ``usecols`` parameter would be ``[0, 1, 2]`` or ``['foo', 'bar', 'baz']``.\n",
" Element order is ignored, so ``usecols=[0, 1]`` is the same as ``[1, 0]``.\n",
" To instantiate a :class:`~pandas.DataFrame` from ``data`` with element order\n",
" preserved use ``pd.read_csv(data, usecols=['foo', 'bar'])[['foo', 'bar']]``\n",
" for columns in ``['foo', 'bar']`` order or\n",
" ``pd.read_csv(data, usecols=['foo', 'bar'])[['bar', 'foo']]``\n",
" for ``['bar', 'foo']`` order.\n",
"\n",
" If callable, the callable function will be evaluated against the column\n",
" names, returning names where the callable function evaluates to ``True``. An\n",
" example of a valid callable argument would be ``lambda x: x.upper() in\n",
" ['AAA', 'BBB', 'DDD']``. Using this parameter results in much faster\n",
" parsing time and lower memory usage.\n",
"dtype : dtype or dict of {Hashable : dtype}, optional\n",
" Data type(s) to apply to either the whole dataset or individual columns.\n",
" E.g., ``{'a': np.float64, 'b': np.int32, 'c': 'Int64'}``\n",
" Use ``str`` or ``object`` together with suitable ``na_values`` settings\n",
" to preserve and not interpret ``dtype``.\n",
" If ``converters`` are specified, they will be applied INSTEAD\n",
" of ``dtype`` conversion.\n",
"\n",
" .. versionadded:: 1.5.0\n",
"\n",
" Support for ``defaultdict`` was added. Specify a ``defaultdict`` as input where\n",
" the default determines the ``dtype`` of the columns which are not explicitly\n",
" listed.\n",
"engine : {'c', 'python', 'pyarrow'}, optional\n",
" Parser engine to use. The C and pyarrow engines are faster, while the python engine\n",
" is currently more feature-complete. Multithreading is currently only supported by\n",
" the pyarrow engine.\n",
"\n",
" .. versionadded:: 1.4.0\n",
"\n",
" The 'pyarrow' engine was added as an *experimental* engine, and some features\n",
" are unsupported, or may not work correctly, with this engine.\n",
"converters : dict of {Hashable : Callable}, optional\n",
" Functions for converting values in specified columns. Keys can either\n",
" be column labels or column indices.\n",
"true_values : list, optional\n",
" Values to consider as ``True`` in addition to case-insensitive variants of 'True'.\n",
"false_values : list, optional\n",
" Values to consider as ``False`` in addition to case-insensitive variants of 'False'.\n",
"skipinitialspace : bool, default False\n",
" Skip spaces after delimiter.\n",
"skiprows : int, list of int or Callable, optional\n",
" Line numbers to skip (0-indexed) or number of lines to skip (``int``)\n",
" at the start of the file.\n",
"\n",
" If callable, the callable function will be evaluated against the row\n",
" indices, returning ``True`` if the row should be skipped and ``False`` otherwise.\n",
" An example of a valid callable argument would be ``lambda x: x in [0, 2]``.\n",
"skipfooter : int, default 0\n",
" Number of lines at bottom of file to skip (Unsupported with ``engine='c'``).\n",
"nrows : int, optional\n",
" Number of rows of file to read. Useful for reading pieces of large files.\n",
"na_values : Hashable, Iterable of Hashable or dict of {Hashable : Iterable}, optional\n",
" Additional strings to recognize as ``NA``/``NaN``. If ``dict`` passed, specific\n",
" per-column ``NA`` values. By default the following values are interpreted as\n",
" ``NaN``: \" \", \"#N/A\", \"#N/A N/A\", \"#NA\", \"-1.#IND\", \"-1.#QNAN\", \"-NaN\", \"-nan\",\n",
" \"1.#IND\", \"1.#QNAN\", \"\", \"N/A\", \"NA\", \"NULL\", \"NaN\", \"None\",\n",
" \"n/a\", \"nan\", \"null \".\n",
"\n",
"keep_default_na : bool, default True\n",
" Whether or not to include the default ``NaN`` values when parsing the data.\n",
" Depending on whether ``na_values`` is passed in, the behavior is as follows:\n",
"\n",
" * If ``keep_default_na`` is ``True``, and ``na_values`` are specified, ``na_values``\n",
" is appended to the default ``NaN`` values used for parsing.\n",
" * If ``keep_default_na`` is ``True``, and ``na_values`` are not specified, only\n",
" the default ``NaN`` values are used for parsing.\n",
" * If ``keep_default_na`` is ``False``, and ``na_values`` are specified, only\n",
" the ``NaN`` values specified ``na_values`` are used for parsing.\n",
" * If ``keep_default_na`` is ``False``, and ``na_values`` are not specified, no\n",
" strings will be parsed as ``NaN``.\n",
"\n",
" Note that if ``na_filter`` is passed in as ``False``, the ``keep_default_na`` and\n",
" ``na_values`` parameters will be ignored.\n",
"na_filter : bool, default True\n",
" Detect missing value markers (empty strings and the value of ``na_values``). In\n",
" data without any ``NA`` values, passing ``na_filter=False`` can improve the\n",
" performance of reading a large file.\n",
"verbose : bool, default False\n",
" Indicate number of ``NA`` values placed in non-numeric columns.\n",
"\n",
" .. deprecated:: 2.2.0\n",
"skip_blank_lines : bool, default True\n",
" If ``True``, skip over blank lines rather than interpreting as ``NaN`` values.\n",
"parse_dates : bool, list of Hashable, list of lists or dict of {Hashable : list}, default False\n",
" The behavior is as follows:\n",
"\n",
" * ``bool``. If ``True`` -> try parsing the index. Note: Automatically set to\n",
" ``True`` if ``date_format`` or ``date_parser`` arguments have been passed.\n",
" * ``list`` of ``int`` or names. e.g. If ``[1, 2, 3]`` -> try parsing columns 1, 2, 3\n",
" each as a separate date column.\n",
" * ``list`` of ``list``. e.g. If ``[[1, 3]]`` -> combine columns 1 and 3 and parse\n",
" as a single date column. Values are joined with a space before parsing.\n",
" * ``dict``, e.g. ``{'foo' : [1, 3]}`` -> parse columns 1, 3 as date and call\n",
" result 'foo'. Values are joined with a space before parsing.\n",
"\n",
" If a column or index cannot be represented as an array of ``datetime``,\n",
" say because of an unparsable value or a mixture of timezones, the column\n",
" or index will be returned unaltered as an ``object`` data type. For\n",
" non-standard ``datetime`` parsing, use :func:`~pandas.to_datetime` after\n",
" :func:`~pandas.read_csv`.\n",
"\n",
" Note: A fast-path exists for iso8601-formatted dates.\n",
"infer_datetime_format : bool, default False\n",
" If ``True`` and ``parse_dates`` is enabled, pandas will attempt to infer the\n",
" format of the ``datetime`` strings in the columns, and if it can be inferred,\n",
" switch to a faster method of parsing them. In some cases this can increase\n",
" the parsing speed by 5-10x.\n",
"\n",
" .. deprecated:: 2.0.0\n",
" A strict version of this argument is now the default, passing it has no effect.\n",
"\n",
"keep_date_col : bool, default False\n",
" If ``True`` and ``parse_dates`` specifies combining multiple columns then\n",
" keep the original columns.\n",
"date_parser : Callable, optional\n",
" Function to use for converting a sequence of string columns to an array of\n",
" ``datetime`` instances. The default uses ``dateutil.parser.parser`` to do the\n",
" conversion. pandas will try to call ``date_parser`` in three different ways,\n",
" advancing to the next if an exception occurs: 1) Pass one or more arrays\n",
" (as defined by ``parse_dates``) as arguments; 2) concatenate (row-wise) the\n",
" string values from the columns defined by ``parse_dates`` into a single array\n",
" and pass that; and 3) call ``date_parser`` once for each row using one or\n",
" more strings (corresponding to the columns defined by ``parse_dates``) as\n",
" arguments.\n",
"\n",
" .. deprecated:: 2.0.0\n",
" Use ``date_format`` instead, or read in as ``object`` and then apply\n",
" :func:`~pandas.to_datetime` as-needed.\n",
"date_format : str or dict of column -> format, optional\n",
" Format to use for parsing dates when used in conjunction with ``parse_dates``.\n",
" The strftime to parse time, e.g. :const:`\"%d/%m/%Y\"`. See\n",
" `strftime documentation\n",
" `_ for more information on choices, though\n",
" note that :const:`\"%f\"` will parse all the way up to nanoseconds.\n",
" You can also pass:\n",
"\n",
" - \"ISO8601\", to parse any `ISO8601 `_\n",
" time string (not necessarily in exactly the same format);\n",
" - \"mixed\", to infer the format for each element individually. This is risky,\n",
" and you should probably use it along with `dayfirst`.\n",
"\n",
" .. versionadded:: 2.0.0\n",
"dayfirst : bool, default False\n",
" DD/MM format dates, international and European format.\n",
"cache_dates : bool, default True\n",
" If ``True``, use a cache of unique, converted dates to apply the ``datetime``\n",
" conversion. May produce significant speed-up when parsing duplicate\n",
" date strings, especially ones with timezone offsets.\n",
"\n",
"iterator : bool, default False\n",
" Return ``TextFileReader`` object for iteration or getting chunks with\n",
" ``get_chunk()``.\n",
"chunksize : int, optional\n",
" Number of lines to read from the file per chunk. Passing a value will cause the\n",
" function to return a ``TextFileReader`` object for iteration.\n",
" See the `IO Tools docs\n",
" `_\n",
" for more information on ``iterator`` and ``chunksize``.\n",
"\n",
"compression : str or dict, default 'infer'\n",
" For on-the-fly decompression of on-disk data. If 'infer' and 'filepath_or_buffer' is\n",
" path-like, then detect compression from the following extensions: '.gz',\n",
" '.bz2', '.zip', '.xz', '.zst', '.tar', '.tar.gz', '.tar.xz' or '.tar.bz2'\n",
" (otherwise no compression).\n",
" If using 'zip' or 'tar', the ZIP file must contain only one data file to be read in.\n",
" Set to ``None`` for no decompression.\n",
" Can also be a dict with key ``'method'`` set\n",
" to one of {``'zip'``, ``'gzip'``, ``'bz2'``, ``'zstd'``, ``'xz'``, ``'tar'``} and\n",
" other key-value pairs are forwarded to\n",
" ``zipfile.ZipFile``, ``gzip.GzipFile``,\n",
" ``bz2.BZ2File``, ``zstandard.ZstdDecompressor``, ``lzma.LZMAFile`` or\n",
" ``tarfile.TarFile``, respectively.\n",
" As an example, the following could be passed for Zstandard decompression using a\n",
" custom compression dictionary:\n",
" ``compression={'method': 'zstd', 'dict_data': my_compression_dict}``.\n",
"\n",
" .. versionadded:: 1.5.0\n",
" Added support for `.tar` files.\n",
"\n",
" .. versionchanged:: 1.4.0 Zstandard support.\n",
"\n",
"thousands : str (length 1), optional\n",
" Character acting as the thousands separator in numerical values.\n",
"decimal : str (length 1), default '.'\n",
" Character to recognize as decimal point (e.g., use ',' for European data).\n",
"lineterminator : str (length 1), optional\n",
" Character used to denote a line break. Only valid with C parser.\n",
"quotechar : str (length 1), optional\n",
" Character used to denote the start and end of a quoted item. Quoted\n",
" items can include the ``delimiter`` and it will be ignored.\n",
"quoting : {0 or csv.QUOTE_MINIMAL, 1 or csv.QUOTE_ALL, 2 or csv.QUOTE_NONNUMERIC, 3 or csv.QUOTE_NONE}, default csv.QUOTE_MINIMAL\n",
" Control field quoting behavior per ``csv.QUOTE_*`` constants. Default is\n",
" ``csv.QUOTE_MINIMAL`` (i.e., 0) which implies that only fields containing special\n",
" characters are quoted (e.g., characters defined in ``quotechar``, ``delimiter``,\n",
" or ``lineterminator``.\n",
"doublequote : bool, default True\n",
" When ``quotechar`` is specified and ``quoting`` is not ``QUOTE_NONE``, indicate\n",
" whether or not to interpret two consecutive ``quotechar`` elements INSIDE a\n",
" field as a single ``quotechar`` element.\n",
"escapechar : str (length 1), optional\n",
" Character used to escape other characters.\n",
"comment : str (length 1), optional\n",
" Character indicating that the remainder of line should not be parsed.\n",
" If found at the beginning\n",
" of a line, the line will be ignored altogether. This parameter must be a\n",
" single character. Like empty lines (as long as ``skip_blank_lines=True``),\n",
" fully commented lines are ignored by the parameter ``header`` but not by\n",
" ``skiprows``. For example, if ``comment='#'``, parsing\n",
" ``#empty\\na,b,c\\n1,2,3`` with ``header=0`` will result in ``'a,b,c'`` being\n",
" treated as the header.\n",
"encoding : str, optional, default 'utf-8'\n",
" Encoding to use for UTF when reading/writing (ex. ``'utf-8'``). `List of Python\n",
" standard encodings\n",
" `_ .\n",
"\n",
"encoding_errors : str, optional, default 'strict'\n",
" How encoding errors are treated. `List of possible values\n",
" `_ .\n",
"\n",
" .. versionadded:: 1.3.0\n",
"\n",
"dialect : str or csv.Dialect, optional\n",
" If provided, this parameter will override values (default or not) for the\n",
" following parameters: ``delimiter``, ``doublequote``, ``escapechar``,\n",
" ``skipinitialspace``, ``quotechar``, and ``quoting``. If it is necessary to\n",
" override values, a ``ParserWarning`` will be issued. See ``csv.Dialect``\n",
" documentation for more details.\n",
"on_bad_lines : {'error', 'warn', 'skip'} or Callable, default 'error'\n",
" Specifies what to do upon encountering a bad line (a line with too many fields).\n",
" Allowed values are :\n",
"\n",
" - ``'error'``, raise an Exception when a bad line is encountered.\n",
" - ``'warn'``, raise a warning when a bad line is encountered and skip that line.\n",
" - ``'skip'``, skip bad lines without raising or warning when they are encountered.\n",
"\n",
" .. versionadded:: 1.3.0\n",
"\n",
" .. versionadded:: 1.4.0\n",
"\n",
" - Callable, function with signature\n",
" ``(bad_line: list[str]) -> list[str] | None`` that will process a single\n",
" bad line. ``bad_line`` is a list of strings split by the ``sep``.\n",
" If the function returns ``None``, the bad line will be ignored.\n",
" If the function returns a new ``list`` of strings with more elements than\n",
" expected, a ``ParserWarning`` will be emitted while dropping extra elements.\n",
" Only supported when ``engine='python'``\n",
"\n",
" .. versionchanged:: 2.2.0\n",
"\n",
" - Callable, function with signature\n",
" as described in `pyarrow documentation\n",
" `_ when ``engine='pyarrow'``\n",
"\n",
"delim_whitespace : bool, default False\n",
" Specifies whether or not whitespace (e.g. ``' '`` or ``'\\t'``) will be\n",
" used as the ``sep`` delimiter. Equivalent to setting ``sep='\\s+'``. If this option\n",
" is set to ``True``, nothing should be passed in for the ``delimiter``\n",
" parameter.\n",
"\n",
" .. deprecated:: 2.2.0\n",
" Use ``sep=\"\\s+\"`` instead.\n",
"low_memory : bool, default True\n",
" Internally process the file in chunks, resulting in lower memory use\n",
" while parsing, but possibly mixed type inference. To ensure no mixed\n",
" types either set ``False``, or specify the type with the ``dtype`` parameter.\n",
" Note that the entire file is read into a single :class:`~pandas.DataFrame`\n",
" regardless, use the ``chunksize`` or ``iterator`` parameter to return the data in\n",
" chunks. (Only valid with C parser).\n",
"memory_map : bool, default False\n",
" If a filepath is provided for ``filepath_or_buffer``, map the file object\n",
" directly onto memory and access the data directly from there. Using this\n",
" option can improve performance because there is no longer any I/O overhead.\n",
"float_precision : {'high', 'legacy', 'round_trip'}, optional\n",
" Specifies which converter the C engine should use for floating-point\n",
" values. The options are ``None`` or ``'high'`` for the ordinary converter,\n",
" ``'legacy'`` for the original lower precision pandas converter, and\n",
" ``'round_trip'`` for the round-trip converter.\n",
"\n",
"storage_options : dict, optional\n",
" Extra options that make sense for a particular storage connection, e.g.\n",
" host, port, username, password, etc. For HTTP(S) URLs the key-value pairs\n",
" are forwarded to ``urllib.request.Request`` as header options. For other\n",
" URLs (e.g. starting with \"s3://\", and \"gcs://\") the key-value pairs are\n",
" forwarded to ``fsspec.open``. Please see ``fsspec`` and ``urllib`` for more\n",
" details, and for more examples on storage options refer `here\n",
" `_.\n",
"\n",
"dtype_backend : {'numpy_nullable', 'pyarrow'}, default 'numpy_nullable'\n",
" Back-end data type applied to the resultant :class:`DataFrame`\n",
" (still experimental). Behaviour is as follows:\n",
"\n",
" * ``\"numpy_nullable\"``: returns nullable-dtype-backed :class:`DataFrame`\n",
" (default).\n",
" * ``\"pyarrow\"``: returns pyarrow-backed nullable :class:`ArrowDtype`\n",
" DataFrame.\n",
"\n",
" .. versionadded:: 2.0\n",
"\n",
"Returns\n",
"-------\n",
"DataFrame or TextFileReader\n",
" A comma-separated values (csv) file is returned as two-dimensional\n",
" data structure with labeled axes.\n",
"\n",
"See Also\n",
"--------\n",
"DataFrame.to_csv : Write DataFrame to a comma-separated values (csv) file.\n",
"read_table : Read general delimited file into DataFrame.\n",
"read_fwf : Read a table of fixed-width formatted lines into DataFrame.\n",
"\n",
"Examples\n",
"--------\n",
">>> pd.read_csv('data.csv') # doctest: +SKIP\n",
"\u001b[31mFile:\u001b[39m ~/miniconda3/lib/python3.13/site-packages/pandas/io/parsers/readers.py\n",
"\u001b[31mType:\u001b[39m function"
]
}
],
"source": [
"?pd.read_csv"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "f59640f4",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[3.60704666e-01, 5.55521539e+00],\n",
" [1.54415346e+00, 9.89094799e+00],\n",
" [2.76704060e+00, 1.39110967e+01],\n",
" [8.16535136e-01, 7.83505417e+00],\n",
" [2.72319697e-01, 5.92490921e+00],\n",
" [6.95010146e-01, 7.46271549e+00],\n",
" [8.24247370e-02, 4.57851162e+00],\n",
" [2.01541232e+00, 1.10609418e+01],\n",
" [4.88964923e-01, 6.24796322e+00],\n",
" [2.33151761e+00, 1.22248394e+01],\n",
" [4.99316650e-01, 6.82276730e+00],\n",
" [2.93206036e+00, 1.39279665e+01],\n",
" [1.63678058e+00, 9.61838868e+00],\n",
" [4.10880624e-01, 5.75266148e+00],\n",
" [1.98564849e+00, 1.13457174e+01],\n",
" [1.14640743e-01, 4.67882850e+00],\n",
" [2.41074536e+00, 1.20510256e+01],\n",
" [2.76277077e+00, 1.37846634e+01],\n",
" [1.16437541e+00, 8.42623547e+00],\n",
" [2.79066087e+00, 1.35375690e+01],\n",
" [5.99142278e-01, 6.91043813e+00],\n",
" [1.79674650e-02, 5.32527941e+00],\n",
" [1.31731753e+00, 9.05937773e+00],\n",
" [2.88622488e+00, 1.35943297e+01],\n",
" [5.11364711e-01, 6.13859655e+00],\n",
" [2.29302952e+00, 1.27819484e+01],\n",
" [7.97442143e-01, 7.28485807e+00],\n",
" [2.18234199e+00, 1.20714830e+01],\n",
" [1.35101620e+00, 9.06843137e+00],\n",
" [1.11966218e-01, 5.47445094e+00],\n",
" [4.16212704e-01, 6.64019585e+00],\n",
" [2.77617723e+00, 1.33598393e+01],\n",
" [4.15397815e-01, 5.76908817e+00],\n",
" [1.91974432e+00, 1.06938529e+01],\n",
" [1.17028044e-01, 5.32928487e+00],\n",
" [1.98092312e+00, 1.15816098e+01],\n",
" [4.88021257e-01, 6.76090080e+00],\n",
" [2.23387170e+00, 1.09670001e+01],\n",
" [2.24244852e+00, 1.16823457e+01],\n",
" [7.97213536e-01, 6.84408491e+00],\n",
" [2.41585592e+00, 1.27823325e+01],\n",
" [1.33783900e+00, 9.02156574e+00],\n",
" [1.49546504e+00, 8.85703368e+00],\n",
" [4.15264699e-01, 6.66094096e+00],\n",
" [1.63853799e+00, 1.05223515e+01],\n",
" [8.64142086e-01, 7.87010562e+00],\n",
" [1.15697870e+00, 8.38907354e+00],\n",
" [8.95836452e-01, 6.85346846e+00],\n",
" [5.69648945e-01, 7.24244714e+00],\n",
" [1.19346962e+00, 8.40456860e+00],\n",
" [8.06454164e-01, 7.07762160e+00],\n",
" [2.58572974e+00, 1.35713373e+01],\n",
" [6.81646790e-02, 5.07763932e+00],\n",
" [1.05308499e-01, 5.33818777e+00],\n",
" [2.54005446e+00, 1.21779668e+01],\n",
" [1.91439231e+00, 1.07811411e+01],\n",
" [1.42152293e+00, 9.26239918e+00],\n",
" [2.93917440e+00, 1.36775455e+01],\n",
" [2.93965607e+00, 1.40967119e+01],\n",
" [8.90288670e-01, 7.81013162e+00],\n",
" [1.12234130e+00, 8.36545238e+00],\n",
" [2.52062974e+00, 1.29832468e+01],\n",
" [2.77805448e+00, 1.31058480e+01],\n",
" [1.97025867e+00, 1.06659512e+01],\n",
" [3.02195069e-01, 6.01233625e+00],\n",
" [1.58181764e+00, 9.58949209e+00],\n",
" [4.34566292e-01, 5.67611255e+00],\n",
" [7.58234990e-01, 7.43094615e+00],\n",
" [1.25965759e+00, 9.41162775e+00],\n",
" [2.76788355e+00, 1.30869578e+01],\n",
" [2.65546305e+00, 1.27026115e+01],\n",
" [1.46798295e+00, 8.79478350e+00],\n",
" [2.95303853e+00, 1.39483396e+01],\n",
" [2.51438561e+00, 1.31103271e+01],\n",
" [1.88729223e+00, 1.09053185e+01],\n",
" [1.59646231e+00, 9.88553130e+00],\n",
" [1.40180995e+00, 8.53063636e+00],\n",
" [1.20718757e-01, 6.19537614e+00],\n",
" [1.75611487e+00, 1.00832243e+01],\n",
" [2.96688013e+00, 1.43125952e+01],\n",
" [2.36040765e+00, 1.28709805e+01],\n",
" [2.25440006e+00, 1.12008558e+01],\n",
" [2.93662778e+00, 1.35769363e+01],\n",
" [1.90084909e+00, 1.00391154e+01],\n",
" [1.00191559e+00, 8.38796917e+00],\n",
" [1.38169992e+00, 8.94932355e+00],\n",
" [1.76684900e-03, 5.44959905e+00],\n",
" [7.67007633e-01, 8.28363102e+00],\n",
" [2.15259592e+00, 1.14376071e+01],\n",
" [1.63911973e+00, 9.75006698e+00],\n",
" [9.87833591e-01, 8.26614534e+00],\n",
" [8.64373539e-01, 7.79806174e+00],\n",
" [1.51709295e+00, 8.59891128e+00],\n",
" [8.48653273e-01, 7.88225421e+00],\n",
" [2.13753229e+00, 1.15994153e+01],\n",
" [2.20556355e+00, 1.21150055e+01],\n",
" [2.28285453e+00, 1.18833568e+01],\n",
" [6.66461180e-02, 3.89723637e+00],\n",
" [1.31710645e+00, 8.53200487e+00],\n",
" [2.33828291e+00, 1.19759795e+01],\n",
" [2.53746748e+00, 1.27533408e+01],\n",
" [2.08157348e+00, 1.06088168e+01],\n",
" [2.69707663e+00, 1.31267225e+01],\n",
" [1.33485837e+00, 8.85867663e+00],\n",
" [1.48740229e+00, 9.71665436e+00],\n",
" [1.59556218e+00, 9.23291903e+00],\n",
" [2.34047209e-01, 6.03314855e+00],\n",
" [2.22578261e+00, 1.15087806e+01],\n",
" [7.93959528e-01, 7.38727244e+00],\n",
" [2.02650615e+00, 1.11653629e+01],\n",
" [1.76581800e+00, 1.00359032e+01],\n",
" [1.81851988e+00, 9.77192328e+00],\n",
" [9.75880676e-01, 7.66532909e+00],\n",
" [2.20594913e+00, 1.10193634e+01],\n",
" [2.71521366e+00, 1.33332404e+01],\n",
" [2.14315799e-01, 5.81627894e+00],\n",
" [1.71338811e+00, 9.48695996e+00],\n",
" [9.31495594e-01, 7.88992704e+00],\n",
" [2.27863167e+00, 1.22342299e+01],\n",
" [4.74303190e-02, 4.69994749e+00],\n",
" [1.41360703e+00, 9.11981669e+00],\n",
" [1.07798400e-03, 4.65883063e+00],\n",
" [7.05387622e-01, 6.72194573e+00],\n",
" [9.87993235e-01, 7.17180346e+00],\n",
" [4.46603023e-01, 6.28147777e+00],\n",
" [1.19754142e+00, 8.83223453e+00],\n",
" [2.08524116e+00, 1.10072003e+01],\n",
" [1.03751325e+00, 8.20063234e+00],\n",
" [1.19137023e+00, 8.77348481e+00],\n",
" [6.94926294e-01, 7.00341494e+00],\n",
" [1.37005714e+00, 9.12379317e+00],\n",
" [8.58150811e-01, 7.43076081e+00],\n",
" [1.21300938e-01, 5.19449051e+00],\n",
" [1.46603042e+00, 9.24726469e+00],\n",
" [7.02542772e-01, 7.48523251e+00],\n",
" [2.77211657e+00, 1.29764319e+01],\n",
" [2.27128976e+00, 1.24748102e+01],\n",
" [2.69719928e+00, 1.28066761e+01],\n",
" [4.67028171e-01, 6.09118913e+00],\n",
" [2.99156807e+00, 1.37961366e+01],\n",
" [1.29851090e+00, 8.39164303e+00],\n",
" [1.30775092e+00, 8.79474665e+00],\n",
" [1.21280410e+00, 8.33307917e+00],\n",
" [1.03327086e+00, 7.58787689e+00],\n",
" [1.54358557e+00, 9.11472212e+00],\n",
" [1.72122873e+00, 1.01457300e+01],\n",
" [2.96034817e+00, 1.30914076e+01],\n",
" [2.73875405e+00, 1.31583141e+01],\n",
" [2.69622698e+00, 1.31822066e+01],\n",
" [1.65373015e+00, 9.79622241e+00],\n",
" [1.64019737e+00, 9.33492210e+00],\n",
" [8.99575422e-01, 7.98371282e+00],\n",
" [2.89483748e-01, 5.40553035e+00],\n",
" [2.41983841e+00, 1.18616729e+01],\n",
" [1.91223302e+00, 1.08729075e+01],\n",
" [1.81570845e+00, 1.02337538e+01],\n",
" [7.59684613e-01, 8.00257618e+00],\n",
" [3.60872973e-01, 5.79919667e+00],\n",
" [1.50141244e+00, 1.02462963e+01],\n",
" [1.45271758e+00, 9.59420048e+00]])"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Your code here \n",
"file1 = pd.read_csv('train.csv')\n",
"df_train = pd.DataFrame(file1)\n",
"#读取数据集\n",
"#使用函数 pd.read_csv\n",
"\n",
"arr_train = np.array(df_train)\n",
"#转化成numpy矩阵\n",
"#使用函数 np.array\n",
"\n",
"arr_train"
]
},
{
"cell_type": "markdown",
"id": "1bccb84d",
"metadata": {},
"source": [
"2) 假设模型为一元线性回归模型$\\hat{y}=wx+b$, 损失函数为$l(w,b)=\\frac{1}{2}\\sum_{i=1}^m(\\hat{y}^{(i)}-y^{(i)})^2$, 其中$\\hat{y}^{(i)}$表示第$i$个样本的预测值,$y^{(i)}$表示第$i$个样本的实际标签值, $m$为训练集中样本的个数。求出使得损失函数最小化的参数$w$和$b$。"
]
},
{
"cell_type": "markdown",
"id": "e011976d",
"metadata": {},
"source": [
"方法① \n",
"\n",
"将$l(w,b)$分别对$w$和$b$求导,得到\n",
"$$\n",
"\\frac{\\partial l(w,b)}{\\partial w}=w\\sum_{i=1}^m x_i^2 -\\sum_{i=1}^m (y_i-b)x_i,\n",
"$$\n",
"$$\n",
"\\frac{\\partial l(w,b)}{\\partial b}=mb -\\sum_{i=1}^m (y_i-wx_i),\n",
"$$\n",
"令上述两式为零即可得到$w$和$b$的解析解:\n",
"$$\n",
"w=\\frac{\\sum_{i=1}^m y_i (x_i-\\bar{x})}{\\sum_{i=1}^m x_i^2-\\frac{1}{m}(\\sum_{i=1}^m x_i)^2},\n",
"$$\n",
"$$\n",
"b=\\frac{1}{m}\\sum_{i=1}^m(y_i-wx_i),\n",
"$$\n",
"其中$\\bar{x}=\\frac{1}{m}\\sum_{i=1}^m x_i$为$x$的均值。\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "c0ff2184",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[31mSignature:\u001b[39m \n",
"np.sum(\n",
" a,\n",
" axis=\u001b[38;5;28;01mNone\u001b[39;00m,\n",
" dtype=\u001b[38;5;28;01mNone\u001b[39;00m,\n",
" out=\u001b[38;5;28;01mNone\u001b[39;00m,\n",
" keepdims=,\n",
" initial=,\n",
" where=,\n",
")\n",
"\u001b[31mCall signature:\u001b[39m np.sum(*args, **kwargs)\n",
"\u001b[31mType:\u001b[39m _ArrayFunctionDispatcher\n",
"\u001b[31mString form:\u001b[39m \n",
"\u001b[31mFile:\u001b[39m ~/miniconda3/lib/python3.13/site-packages/numpy/_core/fromnumeric.py\n",
"\u001b[31mDocstring:\u001b[39m \n",
"Sum of array elements over a given axis.\n",
"\n",
"Parameters\n",
"----------\n",
"a : array_like\n",
" Elements to sum.\n",
"axis : None or int or tuple of ints, optional\n",
" Axis or axes along which a sum is performed. The default,\n",
" axis=None, will sum all of the elements of the input array. If\n",
" axis is negative it counts from the last to the first axis. If\n",
" axis is a tuple of ints, a sum is performed on all of the axes\n",
" specified in the tuple instead of a single axis or all the axes as\n",
" before.\n",
"dtype : dtype, optional\n",
" The type of the returned array and of the accumulator in which the\n",
" elements are summed. The dtype of `a` is used by default unless `a`\n",
" has an integer dtype of less precision than the default platform\n",
" integer. In that case, if `a` is signed then the platform integer\n",
" is used while if `a` is unsigned then an unsigned integer of the\n",
" same precision as the platform integer is used.\n",
"out : ndarray, optional\n",
" Alternative output array in which to place the result. It must have\n",
" the same shape as the expected output, but the type of the output\n",
" values will be cast if necessary.\n",
"keepdims : bool, optional\n",
" If this is set to True, the axes which are reduced are left\n",
" in the result as dimensions with size one. With this option,\n",
" the result will broadcast correctly against the input array.\n",
"\n",
" If the default value is passed, then `keepdims` will not be\n",
" passed through to the `sum` method of sub-classes of\n",
" `ndarray`, however any non-default value will be. If the\n",
" sub-class' method does not implement `keepdims` any\n",
" exceptions will be raised.\n",
"initial : scalar, optional\n",
" Starting value for the sum. See `~numpy.ufunc.reduce` for details.\n",
"where : array_like of bool, optional\n",
" Elements to include in the sum. See `~numpy.ufunc.reduce` for details.\n",
"\n",
"Returns\n",
"-------\n",
"sum_along_axis : ndarray\n",
" An array with the same shape as `a`, with the specified\n",
" axis removed. If `a` is a 0-d array, or if `axis` is None, a scalar\n",
" is returned. If an output array is specified, a reference to\n",
" `out` is returned.\n",
"\n",
"See Also\n",
"--------\n",
"ndarray.sum : Equivalent method.\n",
"add: ``numpy.add.reduce`` equivalent function.\n",
"cumsum : Cumulative sum of array elements.\n",
"trapezoid : Integration of array values using composite trapezoidal rule.\n",
"\n",
"mean, average\n",
"\n",
"Notes\n",
"-----\n",
"Arithmetic is modular when using integer types, and no error is\n",
"raised on overflow.\n",
"\n",
"The sum of an empty array is the neutral element 0:\n",
"\n",
">>> np.sum([])\n",
"0.0\n",
"\n",
"For floating point numbers the numerical precision of sum (and\n",
"``np.add.reduce``) is in general limited by directly adding each number\n",
"individually to the result causing rounding errors in every step.\n",
"However, often numpy will use a numerically better approach (partial\n",
"pairwise summation) leading to improved precision in many use-cases.\n",
"This improved precision is always provided when no ``axis`` is given.\n",
"When ``axis`` is given, it will depend on which axis is summed.\n",
"Technically, to provide the best speed possible, the improved precision\n",
"is only used when the summation is along the fast axis in memory.\n",
"Note that the exact precision may vary depending on other parameters.\n",
"In contrast to NumPy, Python's ``math.fsum`` function uses a slower but\n",
"more precise approach to summation.\n",
"Especially when summing a large number of lower precision floating point\n",
"numbers, such as ``float32``, numerical errors can become significant.\n",
"In such cases it can be advisable to use `dtype=\"float64\"` to use a higher\n",
"precision for the output.\n",
"\n",
"Examples\n",
"--------\n",
">>> import numpy as np\n",
">>> np.sum([0.5, 1.5])\n",
"2.0\n",
">>> np.sum([0.5, 0.7, 0.2, 1.5], dtype=np.int32)\n",
"np.int32(1)\n",
">>> np.sum([[0, 1], [0, 5]])\n",
"6\n",
">>> np.sum([[0, 1], [0, 5]], axis=0)\n",
"array([0, 6])\n",
">>> np.sum([[0, 1], [0, 5]], axis=1)\n",
"array([1, 5])\n",
">>> np.sum([[0, 1], [np.nan, 5]], where=[False, True], axis=1)\n",
"array([1., 5.])\n",
"\n",
"If the accumulator is too small, overflow occurs:\n",
"\n",
">>> np.ones(128, dtype=np.int8).sum(dtype=np.int8)\n",
"np.int8(-128)\n",
"\n",
"You can also start the sum with a value other than zero:\n",
"\n",
">>> np.sum([10], initial=5)\n",
"15\n",
"\u001b[31mClass docstring:\u001b[39m\n",
"Class to wrap functions with checks for __array_function__ overrides.\n",
"\n",
"All arguments are required, and can only be passed by position.\n",
"\n",
"Parameters\n",
"----------\n",
"dispatcher : function or None\n",
" The dispatcher function that returns a single sequence-like object\n",
" of all arguments relevant. It must have the same signature (except\n",
" the default values) as the actual implementation.\n",
" If ``None``, this is a ``like=`` dispatcher and the\n",
" ``_ArrayFunctionDispatcher`` must be called with ``like`` as the\n",
" first (additional and positional) argument.\n",
"implementation : function\n",
" Function that implements the operation on NumPy arrays without\n",
" overrides. Arguments passed calling the ``_ArrayFunctionDispatcher``\n",
" will be forwarded to this (and the ``dispatcher``) as if using\n",
" ``*args, **kwargs``.\n",
"\n",
"Attributes\n",
"----------\n",
"_implementation : function\n",
" The original implementation passed in."
]
}
],
"source": [
"?np.sum"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "210a8d62",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3.041478869915313 4.906073659305301\n"
]
}
],
"source": [
"# Your code here\n",
"#使用函数 np.sum\n",
"# 需要求yi * (xi-x_mean), xi^2, x_mean\n",
"arr_square = arr_train[:, 0] ** 2 # xi^2\n",
"x_mean = np.mean(arr_train, axis=0)[0] # x的均值\n",
"arr_numerator = arr_train[:, 1] * (arr_train[:, 0] - x_mean) # yi * (xi - x_mean), 分子\n",
"omega = np.sum(arr_numerator) / (np.sum(arr_square) - np.sum(arr_train, axis = 0)[0] ** 2 / arr_train.shape[0] )# w\n",
"mean_dis = arr_train[:, 1] - omega * arr_train[:, 0] # 平均偏移量 b\n",
"b = np.sum(mean_dis) / arr_train.shape[0] # b\n",
"print(omega, b)"
]
},
{
"cell_type": "markdown",
"id": "1a04bc78",
"metadata": {},
"source": [
"方法② 梯度下降法。手动实现梯度下降法(不使用机器学习框架,如PyTorch、TensorFlow等)来进行模型的训练。算法步骤如下:1.初始化模型参数$w$和$b$的值;2.在负梯度的方向上更新参数(批量梯度下降、小批量随机梯度下降或者随机梯度下降均可),并不断迭代这一步骤,更新公式(以小批量随机梯度下降为例)可以写成:$$w\\gets w-\\frac{\\eta}{\\left|B\\right|}\\sum_{i\\in{B}}x^{(i)}(wx^{(i)}+b-y^{(i)}),$$ 和$$b\\gets b-\\frac{\\eta}{\\left|B\\right|}\\sum_{i\\in{B}}(wx^{(i)}+b-y^{(i)}),$$ 其中$\\eta$表示学习率,$B$表示每次迭代中随机抽样的小批量,$\\left|B\\right|$则表示$B$中的样本数量。3. 终止条件为迭代次数达到某一上限或者参数更新的幅度小于某个阈值。"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "bad649ed",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3.041478871472472 4.906073656421955\n"
]
}
],
"source": [
"# Your code here\n",
"#使用 for循环,函数 np.sum等\n",
"l_rate = 0.1\n",
"n_iter = 1000\n",
"data_size = arr_train.shape[0]\n",
"omega_2 = 0\n",
"b_2 = 0\n",
"for i in range(n_iter):\n",
" temp = omega_2\n",
" omega_2 = omega_2 - np.sum(arr_train[:, 0] * (arr_train[:, 0] * omega_2 + b_2 - arr_train[:, 1]), axis = 0) * l_rate / data_size\n",
" b_2 = b_2 - np.sum(arr_train[:, 0] * temp + b_2 - arr_train[:, 1]) * l_rate / data_size\n",
"print(omega_2, b_2)"
]
},
{
"cell_type": "markdown",
"id": "844f2a87",
"metadata": {},
"source": [
"方法③ \n",
"\n",
"用矩阵表示,假设数据集有$m$个样本,特征有$n$维$。X=\\left[ \\begin{matrix} x_{11} & x_{12} & \\cdots & x_{1n} & 1 \\\\\n",
" x_{21} & x_{22} & \\cdots & x_{2n} & 1 \\\\\n",
" \\vdots & \\vdots & & \\vdots & \\vdots \\\\\n",
" x_{m1} & x_{m2} & \\cdots & x_{mn} & 1 \\end{matrix} \\right]$,\n",
" 实际标签$Y=\\left[ \\begin{matrix} y_{1} \\\\\n",
" y_{2} \\\\\n",
" \\vdots \\\\\n",
" y_{m}\\end{matrix} \\right]$,\n",
" 参数$B=\\left[ \\begin{matrix} w_{1} \\\\\n",
" w_{2} \\\\\n",
" \\vdots \\\\\n",
" w_{n} \\\\\n",
" b\\end{matrix} \\right]$,则解析解为$B^*=(X^T X)^{-1}X^T Y$。推导过程可参考[这篇文章](https://zhuanlan.zhihu.com/p/74157986)。"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "7f634cfa",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[3.04147887 4.90607366]\n"
]
}
],
"source": [
"# Your code here\n",
"#使用函数 np.c_ np.ones np.linalg.inv\n",
"# 此数据集有160个样本, 特征有1维\n",
"# X = np.hstack((arr_train[:, 0], np.ones(arr_train.shape[0], 1)))\n",
"X = np.hstack((arr_train[:, 0].reshape(-1,1), np.ones((arr_train.shape[0], 1))))\n",
"Y = arr_train[:, 1]\n",
"B = np.linalg.inv(X.T @ X) @ X.T @ Y\n",
"omega_3 = B[0]\n",
"b_3 = B[1]\n",
"print(B)"
]
},
{
"cell_type": "markdown",
"id": "eb16c177",
"metadata": {},
"source": [
"3) 使用求解出来的线性回归模型对测试数据集'test.csv'进行预测,输出可视化结果(比如用seaborn或者matplotlib等可视化库来画出测试数据的散点图以及训练好的模型函数图像)。"
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "b19a5413",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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8eQqQq50RvbWZzpGq7wef1v9tE6HlXwd6nzknvAIUq9ePfXr10+9evWyfXzEiBGqX79+ha9Rq1Yt1apVq8Jjli9frt69e6tevXqKi7M/T7N3716NHDlS9957b8nY448/rscff7zk602bNqlv37569tlny/1e9evX1yeffKLzzjtPmZmZuvjii0seq1GjhqW0I7bEx5tbSAwcWHEB9zAMKTvbvA+IrXdiT35+vr744gudd955kqTt27crMTFRNWrUkCT9+eefSk5OLvnazscff6z//e9/+u6773TooYcGfc6bN2/WH3/8oVNPPdX2ccMw9Morr+jSSy+15OHcuXP19ddfa8qUKUGfJ5yndD7aFvDHs6XCg+8JyMfYtGPHDn333Xcluehx6qmnavTo0XK5XCW/3G63Tj75ZHXr1k0ffvih7r77bnXv3r0kC1977TVddtllSkg4WB+Ki4tL3itOmzZNt912m+6//35Nmzat5BjezyEcPBk5ccA36qUsr8eWqpu+04klX4cjHynhEcQwDNWoUUO1a9e2fdzlcsmwWwKwzDHlFWuPbt26ac+ePT7Nx2PQoEH6448/5HK5tG/fPhUVFal27dpat26devbsqW3btqlpU3Ml6+LiYg0YMEDDhw/X119/rR49euiLL76Qy+XS999/r1tvvVWStG3bNu3cuVOn/bvd1P79+/XVV1+pZs3Q37eB8ElLk4oNuwJeXO5zyr1XElHtn3/+0QMPPFDyZnP06NEyDEPPPvus9u7dq7POOktTp07VOeecU/Kcs88+WwUFBV6vs3//fg0cONBrbO/evZo3b546d+6sevXqeb2hNAxDhmFYstXtdmvPnj3asWOHbr75Zi1fvlyNGzfWd999p2nTpmnQoEGaOnWqVq1apbfeesv29+S5Wujdd9/VSy+95PXml6uFkJYmxWfUUlHZ//VPXy7tSrJ9DvkYW+bMmaOaNWvquOOOU2JiouLi4jRmzBjVrFlT6enpluM/+ugjSeYJwpkzZ2rlypW67rrr9O2332r16tU68cQTddJJJ0kys2///v368ccf9eOPP6pLly6aOvXgPbee928HDhxQTk6O19dPPPFEuScfgUA5ocl6naf3vcb+UrI+1Dm2x4cyHynhEaS4uFjvvfdeufd079y5U/v27bOMP/nkkzr88MO93nhK5mVDxcXFOv/886s0n9LL+L/44osl/z5r1iytXr1aI0aMUN++ffXRRx/p6KOP1pdffqlffvlFmzZtUmpqqrZu3arzzz9fd999t0aMGCFJOv744/Xll19Kkl599VUtXLhQM2bMkCQVFBRQwGORzXYRtbVPsvlk3MP2XklEvZo1a3plxMMPP6zu3bvrk08+0fvvv6++fftacnDFihUll0k+/PDDOvbYY/Wf//xHkvTUU0+pS5cuXlcf7dmzx7KFyauvvqpXX31Vb775pmVOhmGUHP/www+ra9euOu2003TRRRcpNzdXU6ZMUYsWLdS9e3ft27dPK1eu1OzZszVo0CBJXC2EiiU/kawio9B78MPHpb/Lv/+WfIwde/fu1cMPP6zPPvtMd911l0aMGKFUHz/me+KJJ3T99derefPmmjVrlp577jktXLhQEydO1Geffabrr7/e6/jbb79djRs31rx580pOFnrez23atEmnnXZaydeFhYVkF4Ju689bNTt1tmX8BV1X7nNCmY+U8Ajw/fffKy8vT3369FGfPn0qPHbt2rX69ddf1aNHD9Wta27h9OCDD+qpp56yHLtjxw6NGDFCa9asUePGjas1x08++UTjxo1TQkKCNm3apH79+nk9XlBQoKFDh+rFF1/UY489ptTUVDVt2lQffvihzjjjDJ144onq2LGjkpLsz9xLKvcKAEQxmwJ+YoscFW6uLdlc9OFymff/pKSEYG5wjDfeeEPff/+99u7dq/Xr12v06NE66qij9NRTT6l+/fqaOHGivvrqK/Xo0UN9+vTRiSeeqEceeaTk+Z6i/Ntvv6l169Yl4998840aNmzo9b383UO07PGPPfaYbrrpJknSJZdcom7duik/P18ffvihrrvuOnXo0KGkgEviaiGU6/q3rtfGXd7779RZe6kKlt1uF4/kYwyaNGmSzjnnHHXp0sXy2L59+0qyQzKzxrNIrmEYOv/88zVx4kRJZrY89NBD+uijj/TXX3/p+eeft5TwN954Q6effrrGjx+v66+/XsnJyeXOi4xCsBXkFeipo6zdZ5wr3THvHynhESA/P1/btm3TpEmTdOaZZ6pLly5avHixcnJydMUVV1iOLy4uVnGxeanup59+qri4OMu9QJJ05ZVXau7cuRo6dKheeumlas3xzDPP1Jlnninp4Cfh0sFL1rdu3aqdO3dq5cqV2r59uzZs2KC2bdvq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PfRQTZ8+XW+99ZbOPfdc/fPPP/r222+1cOFCnXDCCerXr58mTZrktYrvvn37tHbtWn3//feWLXdK++233yq9fL00t9ut4uJiXXrppXr//fd1//33a9iwYXK5XNqxY0fJ5aAul0uPPvqounfvrosvvlhXX321xo8fry+//FJbtmzR0UcfLcncTu3999/XkiVLVFxcrPbt26tLly668MILNW3aNA0aNEht2rSp4k8SlcnK8r6EqCzDkLKzzeN83Gq0crt2SR07WoaTkwy5cuwDna12UNqYMWM0cuTIkpV2PbfFrF69WnfccYcmTZqkF154QTt37iw5YRkXF6etW7d6FWzPG84XXnhBhmHom2++8bpcs7oMw9C8efO0ZMkSjR07VjNmzNA333xTsnhc9+4H7/W99957S3a14GohZwhLPsq+gCfNMJTjIh9Rsd9//11XX321GjVqpFGjRqlmzZr65Zdf5HK5ZBiG7Qc2559/vtxut7p166Y///zTsuCj2+0u2cqstD179ujll18uyczPPvtMY8eOVYsWLTR8+HAlJSWpS5cu6tSpk1asWKH58+dr4MCBwfmNI+TClY92BfzFVndJuS7HbEVWHkp4BDj33HMtiwM1a9ZM3bt315FHHqmBAwcqLi5OV199tc4//3xlZWVZttGpWbOmzj77bDVt2tR2z3APfwq4pJJLjq677jo9+eSTatq0aclj+/btU2FhodfxAwcOVL9+/ZSfby5kMnnyZJ1++ukl9xp16dJFb775prp06aLmzZt7PTcvL0/PPfec7r//fr/mCN/5enlOwC7jMQzJ7qSQYWjyv5c1OWUrCTiTYRi64IILdPnll2vHjh0l40uWLNE111yj5557ruRy7cWLF+uGG27QhRdeqOTkZL388stKKfV/4ri4OL3yyivq3Lmz9u/fr5UrV5YU+ooUFxeXXL5ZmezsbL3++uvq1KmTDhw4UDLeqFEjLV261PY5XC3kDCHPR9kXcCPdUGZX8hGVO/zwwzV48GBdccUVJe/vPO+39uzZY/ucd999V2+9Za7DYrfjwr59+1RQUGAZnzVrlmrWrFnyoUrdunX16quvqkuXLjrssMO87ik/5ZRTlJ6eTgmPIuHIR7sC/n+r/09df60dEflICY9QF1xwgS644ALLeOPGjdW/f3/LeHx8vHKCuAJ82VWAJXPv3tKrtXvU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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Your code here\n",
"#A=np.array([[1,2,3],[4,5,6],[7,8,9]])\n",
"#x = A[0, :] #从一个矩阵中提取出一行作为一个向量\n",
"#y1 = np.array([2, 3, 5])\n",
"#plt.plot(x, y1) #画出折线图\n",
"#y2 = np.array([2.5, 2.8, 5.3])\n",
"#plt.plot(x, y2, '.') #画出散点图\n",
"#plt.show()\n",
"import matplotlib.pyplot as plt\n",
"plt.rcParams['font.sans-serif'] = ['WenQuanYi Zen Hei'] # 使用黑体\n",
"plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题\n",
"file_test = pd.read_csv('test.csv')\n",
"df_test = pd.DataFrame(file_test)\n",
"arr_test = np.array(df_test)\n",
"x = arr_test[:, 0]\n",
"y = arr_test[:, 1]\n",
"y1 = omega * x + b\n",
"y2 = omega_2 * x + b_2\n",
"y3 = omega_3 * x + b_3\n",
"# fig, (ax1,ax2,ax3) = plt.Subplot(1,3, figsize=(15,5))\n",
"fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(12, 4))\n",
"\n",
"ax1.scatter(x, y, color=\"blue\", label=\"data\")\n",
"ax2.scatter(x, y, color=\"blue\", label=\"data\")\n",
"ax3.scatter(x, y, color=\"blue\", label=\"data\")\n",
"# 三条拟合直线\n",
"ax1.plot(x, y1, color='red', label=\"最小二乘法\", linewidth=2)\n",
"ax2.plot(x, y2, color='green', label=\"梯度下降法\", linewidth=2)\n",
"ax3.plot(x, y3, color='purple',label=\"矩阵法\", linewidth=2)\n",
"\n",
"ax1.set_xlabel(\"x\")\n",
"ax1.set_ylabel(\"y\")\n",
"ax2.set_xlabel(\"x\")\n",
"ax2.set_ylabel(\"y\")\n",
"ax3.set_xlabel(\"x\")\n",
"ax3.set_ylabel(\"y\")\n",
"ax1.legend()\n",
"ax2.legend()\n",
"ax3.legend()\n",
"plt.show()\n"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "ef9a0e2a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.170268086968883 0.17026808696995938 0.17026808696888246\n"
]
}
],
"source": [
"l1 = np.sum((y - y1) ** 2) / y.shape[0]\n",
"l2 = np.sum((y - y2) ** 2) / y.shape[0]\n",
"l3 = np.sum((y - y3) ** 2) / y.shape[0]\n",
"print(l1, l2, l3)"
]
},
{
"cell_type": "markdown",
"id": "f227579c",
"metadata": {},
"source": [
"4) 在训练数据集'train2.csv'上求一个三元线性回归模型$\\hat{y}=w_0 + w_1 x_1 + w_2 x_2 + w_3 x_3$的使得损失函数$l(w_0,w_1,w_2,w_3)=\\frac{1}{2}\\sum_{i=1}^m(\\hat{y}^{(i)}-y^{(i)})^2$最小的参数$w_0,w_1,w_2$以及$w_3$。并在测试数据集'test2.csv'上进行预测,输出预测结果的均方误差$MSE(\\hat{y},y)=\\frac{1}{n}\\sum^n_{i=1}(y^{(i)}-\\hat{y}^{(i)})^2$, $n$为测试集中样本个数。"
]
},
{
"cell_type": "markdown",
"id": "2a1f6178",
"metadata": {},
"source": [
"方法① 同2)中的方法③。"
]
},
{
"cell_type": "markdown",
"id": "f4ea8a93",
"metadata": {},
"source": [
"方法② 类似2)中的方法②。算法步骤如下:1.初始化模型参数$w_0,w_1,w_2,w_3$的值;2.在负梯度的方向上更新参数(批量梯度下降、小批量随机梯度下降或者随机梯度下降均可),并不断迭代这一步骤,更新公式(以小批量随机梯度下降为例)可以写成:$$w_j\\gets w_j-\\frac{\\eta}{\\left|B\\right|}\\sum_{i\\in{B}}x_j^{(i)}(w_0 + w_1 x_1^{(i)}+w_2 x_2^{(i)}+w_3 x_3^{(i)}-y^{(i)}), j=0,1,2,3,$$ 其中$x_0^{(i)}=1$, 其中$\\eta$表示学习率,$B$表示每次迭代中随机抽样的小批量,$\\left|B\\right|$则表示$B$中的样本数量。3. 终止条件为迭代次数达到某一上限或者参数更新的幅度小于某个阈值。"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "115f58e2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1.00723001 2.00339371 3.01025624 5.94254393]\n"
]
}
],
"source": [
"# Your code here\n",
"file1 = pd.read_csv('train2.csv')\n",
"df_train = pd.DataFrame(file1)\n",
"train_arr = np.array(df_train)\n",
"# 矩阵法\n",
"X = np.hstack((train_arr[:,0:3], np.ones((train_arr.shape[0], 1))))\n",
"Y = train_arr[:, 3] \n",
"B = np.linalg.inv(X.T @ X) @ X.T @ Y\n",
"omega_4 = B[0:3]\n",
"b_4 = B[3]\n",
"print(B)"
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "66d59805",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[5.94171807 1.00732908 2.00349462 3.01036272]\n"
]
}
],
"source": [
"# omega - (4,) b - () omega * x \n",
"l_rate = 0.01\n",
"n_iter = 9000\n",
"data_size = train_arr.shape[0]\n",
"omega_5 = np.zeros(4)\n",
"Y = train_arr[:, 3]\n",
"train_arr = np.hstack((np.ones((train_arr.shape[0], 1)), train_arr[:,0:3]))\n",
"for i in range(n_iter):\n",
" bias = train_arr @ omega_5 - Y\n",
" grad = (train_arr.T @ bias) / data_size # (4,)\n",
" omega_5 = omega_5 - l_rate * grad\n",
"print(omega_5)"
]
},
{
"cell_type": "code",
"execution_count": 38,
"id": "7956cd4e",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA0gAAAGHCAYAAACKxnKTAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAguxJREFUeJzt3XlcVGX7x/HPAIoruCs64L5vZWVqYWhWtpiJZGql/myzFSpbTCvLMp+2B7RdSyvLUhqzrHzKEqPUTMvdXMoFCXNLQFGWmfP7Y5yRYWZgQHa+79eLl859lrk54lxc577PdZsMwzAQERERERER/Mq6AyIiIiIiIuWFEiQREREREZEzlCCJiIiIiIicoQRJRERERETkDCVIIiIiIiIiZyhBEhEREREROUMJkoiIiIiIyBlKkERERERERM5QgiQiIiKSj4MHDzJv3ryy7oaUoKSkJLZu3VrW3ZByQgmSiIiISD5Wr17N7bffzg8//FCk47Ozs7HZbB63ZWVleT1uxYoVrF+/3qVt//79PidrP//8M82aNSM1NdXnvhaXU6dOYbVana+tVis2mw3DMDAMw+Mxn332Gb///rtbe2ZmJu+//z4nTpxwabdYLGzZsqVY+vv2228zYcIEt/ZvvvmGV155xeMxMTEx3HPPPcXy/lK+KEESERERycewYcN48MEHGTlyJH///bfX/ebMmUPdunXp1q0b3bp1IyAggOeee46nn36a+vXr06xZM5evRo0aUb9+fTIzMz2eb/LkyXz00UcubTt27ODxxx/3qd9Wq5V//vmHgIAAn7/XdevW0b59e+f30K1bNxo1akStWrXo3bs3F110EX369OHiiy/mwgsvpE+fPvTp04fevXvTvXt3jhw5AsBTTz3F888/7zxvixYtaNOmDZ07d6Zz587UqlXLLdGbOXMmCQkJbn1auXIlt99+u1sy+corr/DTTz/5/L3lJzAwkMDAQLf2devWsXDhQo/HpKenk5aWVizvL+WL7/9jRERERCq5kSNHsmbNGrd2q9XK4cOHueiii6hWrZrb9k8++QSASy65hGXLlvH9998zatQoJkyYQKNGjZg+fXqh+nHs2DHWrl1LaGgonTt3dv7yfuLECY4dO8Z5553n0reQkBC+/fZbl3M4+pmUlFRgkpSTk0O1atW48MIL2bVrF7/99htBQUFs2LCBhx56iG+++YYLL7wQk8kEwEMPPcSnn35KUlISfn72++2GYTi333HHHfTu3ZtBgwbRr18/5zXq06cPABEREW598JakfPPNN/Tv35++ffsSGBjofL/du3eTlJTEW2+95dz31KlTvPLKK1x33XV8/PHH3H777VSvXt3lfH369GHZsmVu18rTNfLWJ8cxuUfJpPJQgiQiIiJyxsGDB5kyZQq33347AMePH6devXr5HtOsWTNOnz7tfG21WnnwwQd59tlnadSoUZH6sWTJElq0aMFHH33k8ov7Tz/9xC233MKGDRtc9vc0bc2RrOROprzJzs7moosuciaHr7/+Ol9++SX+/v589913dOvWzbnvgQMHmD17Ni+99JIzWcn9fgAdOnQgLi6O33//3ZkggT2Byf39zJ07l9dee43169fj5+fncj6wX8slS5YwefJkxo8f7/IegwYN4pZbbmHcuHEer8WAAQMYOXIk06dPp0aNGgBMnz6dAwcOYLVa8fPzczlf7vc0mUzO/uTtU3527NhBs2bNCA4O9vkYKX+UIImIiIh4sHz5csaOHcuKFSvo0KEDiYmJzJs3j3fffdfj/o5ftufMmQPYR1GKwmq18uKLL3LPPff4PD3O0y/6DidOnPDpPLmTrDfeeIPt27dTo0YNunTp4mxv1KgR7dq1Y+DAgSxfvpzly5dz8uRJvvvuO7Zu3UrHjh05cuQIJ0+eZOzYsW7vccUVVzBs2DDna39//3z79Mknn5Camsro0aPz/R5zc+xnGAaLFi2iTZs2TJkyBYANGzYwaNAgbr75Zj799FPn+zuejfL398dms/Hll19y3XXX+fR+Dn/++ScDBgxg8ODBvPfee4U6VsoXPYMkIiIicsYrr7zCNddcA0B4eDg9e/Zk4MCB7N69m4MHD/L999+7HbNo0SJ69uwJ2H/RbteuHQ0bNsTf358ePXoQHBxMo0aNaNSoEcHBwdSrV8/5ulGjRtStW9dlFOT555/njz/+4MYbbwTso0bVq1enW7duTJgwgTp16jifDzKZTOzdu7dYvneTyUR8fDwdOnTg4osvJiUlhZUrV3LeeefRpUsXpk+fTk5ODjExMTz//PNceOGFLFy4kFmzZmG1Wp0J1vz587npppvIzs52e4+8U9aqV6/uccoiwKFDh5g4cSLXXnstNWvWBOyjRmazmW7dunHw4EFefvllunXrRpMmTdxGkpo3b86TTz7J9OnT2bdvH6dPn2bNmjVccsklzJ07l4yMDE6fPs3p06eZNm0aV1xxBadPnyY9PZ3Bgwc7z5Odnc2RI0c4cuQIhw8f5u+//+bkyZMu77VhwwbCw8Np2rSp16IOUnEoQRIRERE544ILLqB58+a88sorLFiwgMWLF9O9e3e+/fZbAgMD3Z5nAXsiVb9+fefryy+/nODgYCwWCxs3biQ1NdX5C/awYcOYMGGC8/WRI0dIT09n7ty5gP15m2nTpgG4vFfz5s3ZsmWL25cv/vnnHw4ePJjv1/HjxwEYPnw4O3fuZMOGDTz99NOEh4cze/Zs9uzZw4ABA5zn3Lx5M5MmTfI4qnP//fdTrVo1nn32WbfCCt6e9ckrMzOTUaNG8c8//7hd8+eee87tOnirJhcTE0NoaCgPPvggX375JbVq1aJv375kZWXxn//8B39/fwICApzT7apVq0adOnVc+rh69WrMZjNms5kWLVrQokULFixYANhH+2JjY+nbty8XXnghP/74o8vPglRMmmInIiIiksfp06e57bbbsFqtfP3115hMJpYuXZrv8yi5k4V77rmHGTNmEBkZCdiTBseUs6ysLMaPH8/EiROd09dMJhMrVqxg+PDh/Pe//2XixIku5/77779dngMqDLPZXOA+48aNY+7cuR4TnieeeILHHnuMvn37AvZRssDAQKpVq+Zxf39/fz755BOOHj3KlClTePHFFwvV3+zsbKKiojh48CAxMTFuleKmTJnCyy+/7NJ26NAh58hfbtWrVycuLo6rr76ajRs3MmrUKPz8/Pj77795/vnnadWqldvIU179+/d3qa7nmI63bt06PvroI7755htmzZrlfG5NKj6NIImIiIjkMXnyZF555RXuvPNO3n//fZ+Pc0wzu+yyy1i3bh0ZGRn89ttvvPbaa86pZNWrV2f//v1MmDDB5bmfDh068O6773Lfffe5nbcoI0h9+vRx/jKf39ewYcPyLSYxf/58nnjiCZfvsaDiBS1atKB27do0btzYbVtBzxIFBARw0003sWLFCpo0aeK2vTAjSACDBw/m+uuv56+//uLuu+8GoHPnztx111288MIL+fbFE0cBB7CPHv71119KjioZjSCJiIiInGG1Wp0P7sfExNCwYUMuvPBCn47LLTAwkPbt27Nt2zZee+01+vbt63xOCeDNN9+kR48evPfee9x2222APakYNWqUx/P7OoKUk5Pjc0EGq9VKQEAAhw8f5uKLL/a6b0hIiNuxvli5ciUXXXSR8xjDMDh27JhLhTdv1fduueUWr+ctzAgSnF0PCiAhIYEOHToA9lG9BQsWsGvXLp++H09at25NUFBQkY+X8kkJkoiIiAj2tYc6depEjRo1PI6OpKWl8e+//1K/fn2XX/Kzs7Pp0aMHI0aMcNm/fv36/Pbbb3z00Ud89dVXLtvat2/PpEmTmDRpElFRUQWWhXaMIOWVdzSmXbt27Nu3r8DqcFarleHDhxMfH8/hw4d9LkduGAY2m83je+eVmJjoLDSRmZlJVlYWBw4ccEm4srKy3J5TKshzzz3nNi1u6tSpXotVzJgxgx07dnDrrbfy5JNPMnLkSIKCgujYsSOHDh0q8FrldeDAgXy3Hz16lIYNGxbqnFK+KEESERERARo0aMChQ4c8brPZbPTv35/du3dz+vRpYmNjueGGG1z2mTt3rnNEJDU1lY0bN7J//34GDx7MlVde6XbORx55hDlz5vDss88WW+Wz5cuXYxiG18pwDllZWdSqVQuAw4cPe5wK54kj0Tl27FiBxQgOHDhA3bp1AXv1ucOHD3P8+HHatGnD3LlzqV+/PitXrqRTp04+vXdRrF27lmeeeYZ58+Zx7bXX0r59e6ZNm8ZLL70EFFxmPK/ExERGjBhBbGys130efvhh6tevz3//+99z6bqUIT2DJCIiIpKPnJwc7r77bg4fPszOnTu5++67GT58OI899pjb1DqA3bt306tXL44cOcI///zDG2+84fG8NWvW5IUXXuC9995zK0SQl2OKXd6vvNq1a0f79u1p1apVvl8dOnTAbDaTk5PDv//+6/MI0pVXXklISAiffvop559/PkOHDmXbtm3cfPPNLqNgW7dudRkpio+P59dff6Vr16506dKFX375hXr16jF06FA+/vhjn97bYcqUKW7XwdM1Xr9+PYMHD+bWW29l9OjRBAcHM3XqVD744AMyMjIK9Z5gXzx36NChzJkzh5tuusnrfrt376ZNmzaFPr+UH0qQRERERLxITEykb9++JCQksGzZMoKCgnjhhRdYvHgxb7/9Ntddd50zuXFMOWvbti133303derUYd68eYSGhno9/+jRo9m+fXuBz7GcS5nv/Bw9ehTDMHxOkL744gt+++031qxZw7Rp07Bardx0001cc801LgnRkiVLnM8fAaxbt44333yTOXPmMGXKFG6++WZnaXMHm83m02KwvhRp2LJlC4MGDWLgwIG88847zvY777yTLVu2OEfPHHJycry+d2ZmJrfddhvPP/88y5cv59prrwWgYcOGbNu2jZ07d7J79252797Ntm3b2Lx5M507dy7w+5DyS1PsRERERM7Iyclh586drFixgvnz57Nx40buvPNOpk2b5pwuBnD99dezevVqhgwZQt++fVm6dCnZ2dlkZ2djMpmYOHEit956K02bNgXszy/Fx8ezceNGlyllJpOJZs2aufUj97M+vjIMw6cEA+C1114jPT2dLVu2EBgY6FIK/NChQxw+fJgtW7bQoEEDZ/uWLVuYPHkyK1euZPHixfTq1YsvvviCxx9/nJtvvpmtW7fy3HPPYTKZsFgsxMXFAfaFbkeOHMlzzz1Hz5496dmzJ0lJSUybNo3Ro0ezbt06duzYwZYtW3jggQfcvifHl6/fm2EYdOnShU8//ZSIiAiXaXQBAQEu0wl//PFHfvvtNxYvXswFF1zgdq79+/ezZs0a0tPTWbNmDWFhYc5td911F0uWLKFjx44ux9SsWZNevXr51Fcpn0yGr6VIRERERCoxwzC4++67mTNnDj179mTo0KHcfffd+T6fc/ToUYYPH06DBg0YOHAgH330EatXr/a4b1hYGF27duXDDz8scMTGz8+PWbNm8corr1CjRg0Mw/D4vIyjat2pU6d4/vnnGTlypE/f63333cd7771H69atee655xg2bJhz25YtW7jkkkvo2rUrr732Gl27diUqKopvvvmG4cOHM2PGDFq3bu1yvg8++IA777yTDz74gF69etGxY0fS0tLIzMxk2LBh3HrrrS6lsG02G8nJyYSGhvLxxx8THR3NNddcw9tvv02NGjWc+z377LP8+eefpKSksG/fPmd58bzJkiOZNAyD4OBg1qxZ49N1+Pbbbxk1ahS9evXinXfecfu+XnrpJZYtW4bFYvFaSMNqtbpU4yuoBLqUf0qQRERERM44efIkNpvNZbSoINnZ2Zw4cYLAwEBOnTp1zhXMDMPgxhtvZNasWW4ltsvKnj17qFu3br6J3aFDh2jSpAmGYbBlyxa6d+9+zu/76aefcvDgQaKjo8/5XEVhs9mwWq0FFr2QykUJ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8tZbb9GsWTO3ferWrUuPHj1ITU1l5syZ1K1bl1WrVjFjxgwuueQStmzZwowZM3jggQdo2LChZjiIlJXZs+HOO12abC+9SLOoi/i4FEbGtQ5SERSmHG5JiY2NJSEhgccffxyAlStXUq9ePb755hvGjx/vEnzuv/9+atWqxfjx472ez2w2M3XqVO677z6ysrKK3K933nmH9u3bc+DAAR599FGaN2/OvffeS+3atbn33nu57777uPTSSznvvPPYtm0bV155pcvx33//PRdddBFLly5l1apVWCwWAgICWLFiBT/99BM//fQTq1atUnIkUhy+/dYtOeLOOzFt3UpEBIwaZS/preSoYiir9UIccnJyWLFiBb/99huvvPIKaWlpNGzYkOXLl/PWW29x/vnns3z5ct599126du3qcqxjtgPAzJkzGTlyJCNHjmTFihUFFhRy6N69O1u3bsVkMtGzZ0+WLVvmto/JZOKxxx5j2rRpfP3115x//vmMGzeOp59+mqioKNauXcuRI0do27YtMTExAM4ZDk2aNGHevHke1+vLraDtIlKACRPckiOWLcNv4iNEtIpgVPdRRLSKKNFpwxpBKgJfy9yWZDnchx9+mPr165OSkuIsrjBo0CC+/PJL5s2b55zbfe+992KxWFi9erXX0SOHBx54gHnz5jF37lzuuuuuIvXrhhtuYNSoUdStWxeAsWPH0rJlS6pXr86YMWNISEjgl19+8diX/fv3U7NmTZdtL730EpMnTyY0NJRPPvmEdu3aceGFFxapbyKSy3//Cw895Nr29tvuQUkqjLJaL8Thiy++4IILLuDAgQN8/PHHDBgwwCXxcTjvvPM477zzXPt2ZkrGa6+9Rk5Ojsu2wkxZc8yeePvttxkxYgS//fYb7dq1c3mf/v37c/fdd/Poo48yY8YMrrzySkwmEwEBAWRnZ/P6668zY8YMjh075jxOMxxESkm3brB1q2vbjh3uN/NKmBKkIvC1zG1JlsN1FDh45513sFgspKSkMHHiRPr06UOnTp3o27cvAKNGjeK+++5zm87gSUBAAN98843HaQm+atKkCWC/kxgdHc2ePXv44IMPuO6663j00UfZt28fo0ePZu7cudSuXdvl2E8//dSl+MTevXv57bff+O677wDIysritttuY926dfmuoSEiBRg9GhYscG1budJtrrdULL6uA1Lc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/5GRkcGuXbs4cuQIvXr1Oqf3FKlSbrkFPvrItS0hAS67rEy6U9zKLEE6duwYV199Na+//jojR47EZDJx4MABPvroI/r37891113HmDFjGDhwIB06dGDXrl28/PLLLFy4sOQ6dfAgJCeX3PnP0YgRI3jwwQdJSkqiQYMG/PDDD7z++uvO7Y5pcN40a9bMOTVk3Lhx3H333UyZMoXExETatWtHkyZNPB63bt0655QFxzNI1atXZ//+/axYsYKXX36ZEydO0KpVK5fjJkyYwNVXX82oUaM4dOgQLVu25KqrrqJDhw7s3LmTmTNn8tdff9Em7xouImL33HPw5JOubR98ALfeWjb9qQIUmwrP0827fv360alTJ4/733jjjYwbN44LLriAmTNnUqtWLT777DOuvvpqqlevTr9+/ejXr9859em9994DYO7cuRw6dIi3336bL774gnXr1rF9+3a2bt3K1VdfTc2aNWndujUDBgxQgiTiC8OwL0R+4IBr+549kOf3wIqszBIks9nMihUrmDx5Mo8//jhgf/bllltu4ZFHHiEgIICZM2dy4403kp6eTp06dZg1a1bJllFt1qzkzl0M7xsUFOQc+WnRogXXX389Jh8WgszJySEgIIBjx47R8EwlkYEDB5KZmclPP/3kNhKV14UXXljoZ5AefvhhFi9ezB133MGoUaP4999/ef3112nbti2BgYHMmjWLr7/+mltvvZVdu3Zp7rdUeVYrJCZCSgqEhMBlLw/B9NVS151++QV69y6bDlYRik2Ff19PN++2b9/OpEmT8j2ue/fuWCwWbrnlFt59913nNG9Pbr/9durUqZPvM0i7d+92OWbTpk1MnTqVlStXUrNmTWrWrMnll1/ufKZp/vz5ZGdnExwcrBkMIh5YbVYS9yeSkp5CSN0QwptdjH/NWu47pqeDl8dfKqoyLdLQs2dPli5d6nX7DTfcwA15p5aUJB+mEpS1cePGMWHCBJo2bcpbb71F586dOXz4MAGeSisC2dnZXHrppXzyyScABAcHA+Dn58eYMWOIi4tj/fr1vJu3ZPA56tChAx9++CFt27alTZs21K5d27mtffv2NGnShJEjR7Jw4UIlR1LlWSwQHe24IWeQTl1MnHTdKTkZmjcvi+5VOYpNhePp5l01HypXOUae+vXrx/Hjx/MtMDRnzhwiIiL45JNPWLZsmbOI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FSk2gwYNcgtEv/76Kz179qR69erONpvNxoQJE7j22mu56qqr3M6zd+9ebDYbbdq0cWmPjIzk0Ucfdb7+7bffuOWWW+jcuTPHjx/HZDLxzz//8O+//9KpUyfne/Xu3ZsZM2YU57cqIiIVhGKTSOEElHUHRCqT5cuXAzBjxgzn9IJt27bRr18/6tSpA8A111xD7969AThy5AgHDx5k7969APz555+0bdvW47nnzZvHmjVrXNoWLFjAvffey7333utsi4+PZ/ny5bz11lvF+r2JiEjFpNgkUjhKkERKwIwZM9iwYQMA48aNc7bHxsaydu1aZxDy9/fHbDYDsGPHDvr27cvSpUvp168f3bt354svvqB169YA1KlTh4YNGzrPtWfPHubNm8f+/fsBuP322/njjz84evQox48fZ8uWLQDMmjWL888/v6S/ZRERKecUm0R8owRJpASYTCaX4OOwd+9eJk6c6Hxdv359fvrpJ7KysgB4++23GTJkCL/++isnT54kIODsf9GoqCiioqIAOHXqFDfddBMANWvWBGDDhg3Ex8fTqlUr5zE33HCD2xxzERGpmhSbRHyjBEmkBJhMJhISEtzap06d6nH///3vf9xxxx2sXLmSH374gTZt2lC9enWqVavmtu/p06cZMmQIF110EX///bfLtpEjR1KjRg3n6y1bthATE3Mu34qIiFQSik0ivlGCJFJCIiIi3Nry3qVzGDJkCPfffz+XX345P/74Y77nDQgIYMSIEdx2220sWbLEZdsnn3zidpdORETEQbFJpGBKkERKgMlk4rnnnnNrf++991xe22w2TCYTJpOJyZMn06BBA/z9/b2e12q1EhAQwJ133ulxu+7SiYiIN4pNIr5RgiRSQg4ePOjWduLECZfX3333HVOmTCEwMNDZ9tFHH2Gz2dixYwddunShS5cugH1didOnT7N69WqXsqy56S6diIjkR7FJpGBKkESKyQMPPMDmzZvx9/cnKyuL1157zeVBVoC//vqLrVu38vnnn3Pq1ClmzJjBr7/+6naut99+G6vVyr59+wgPD+e5557L9+6dg+7SiYhIbopNIoWnBEmkmMycOROw30175plnWLp0Kb/++ismkwmAVatWce211zJp0iTuuOMOj+ewWq3ExsbyxhtvOOd7jxgxgiuuuIJFixa5lFL1RHfpREQkN8UmkcIzGYZhlHUnRCqL9evX8+ijj3L69Gk+/fRT5zoSDr/++itjx46ldevWvPvuuzRr1gywT3mwWCzExcXRoUMHZs+e7dyWnZ3NAw88wLfffssXX3xB165dnedr2LAhjz32GEuXLmXz5s106tTJZUrE9u3bad68ObVq1fLYHxERqfwUm0QKyRCRYrFo0SLjggsuMD744APDarV63e/06dPGE088YezZs8c4fvy40adPH6NZs2bG2LFjjXXr1nk9btasWUbr1q2NzMxMwzAMw2azGWPGjDFsNluBffNlHxERqXwUm0QKTyNIImXs33//pX79+j7tm5aWRlBQUAn3SEREqjrFJqnKlCCJiIiIiIic4VfWHRARERERESkvlCCJiIiIiIicoQRJRERERETkDCVIIiIiIiIiZyhBEhEREREROUMJkoiIiIiIyBlKkERERERERM5QgiQiIiIiInLG/wNuZUqc4iJacwAAAABJRU5ErkJggg==",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"file_test = pd.read_csv('test2.csv')\n",
"df_test = pd.DataFrame(file_test)\n",
"test_arr = np.array(df_test)\n",
"x1 = test_arr[:, 0]\n",
"x2 = test_arr[:, 1]\n",
"x3 = test_arr[:, 2]\n",
"y = test_arr[:, 3]\n",
"y1 = omega_4[0] * x1 + omega_4[1] * x2 + omega_4[2] * x3 + b_4\n",
"y2 = omega_5[1] * x1 + omega_5[2] * x2 + omega_5[3] * x3 + omega_5[0]\n",
"fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))\n",
"ax1.scatter(y, y1, color=\"blue\", label=\"最小二乘法\")\n",
"ax1.plot(y,y, color='red', label='y与y\\'曲线', linewidth=2)\n",
"ax2.scatter(y, y2, color=\"green\", label=\"梯度下降法\")\n",
"ax2.plot(y,y, color='red', label='y=y\\'曲线', linewidth=2)\n",
"ax1.set_xlabel(\"真实值\")\n",
"ax1.set_ylabel(\"预测值\")\n",
"ax2.set_xlabel(\"真实值\")\n",
"ax2.set_ylabel(\"预测值\")\n",
"ax1.legend()\n",
"ax2.legend()\n",
"plt.title(\"实际值与预测值对比\")\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 39,
"id": "07e0a55b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.16537691128176946 0.1653678705896775\n"
]
}
],
"source": [
"l4 = np.sum((y - y1) ** 2) / y.shape[0]\n",
"l5 = np.sum((y - y2) ** 2) / y.shape[0]\n",
"print(l4, l5)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}