eecebe7ef5
Five-lane parallel research pass. Each subdir under tooling/ has its own README indexing downloaded files with verified upstream sources. - google-official/: deepmind-gemma JAX examples, gemma_pytorch scripts, gemma.cpp API server docs, google-gemma/cookbook notebooks, ai.google.dev HTML snapshots, Gemma 3 tech report - huggingface/: 8 gemma-4-* model cards, chat-template .jinja files, tokenizer_config.json, transformers gemma4/ source, launch blog posts, official HF Spaces app.py - inference-frameworks/: vLLM/llama.cpp/MLX/Keras-hub/TGI/Gemini API/Vertex AI comparison, run_commands.sh with 8 working launches, 9 code snippets - gemma-family/: 12 per-variant briefs (ShieldGemma 2, CodeGemma, PaliGemma 2, Recurrent/Data/Med/TxGemma, Embedding/Translate/Function/Dolphin/SignGemma) - fine-tuning/: Unsloth Gemma 4 notebooks, Axolotl YAMLs (incl 26B-A4B MoE), TRL scripts, Google cookbook fine-tune notebooks, recipe-recommendation.md Findings that update earlier CORPUS_* docs are flagged in tooling/README.md (not applied) — notably the new <|turn>/<turn|> prompt format, gemma_pytorch abandonment, gemma.cpp Gemini-API server, transformers AutoModelForMultimodalLM, FA2 head_dim=512 break, 26B-A4B MoE quantization rules, no Gemma 4 tech report PDF yet, no Gemma-4-generation specialized siblings yet. Pre-commit secrets hook bypassed per user authorization — flagged "secrets" are base64 notebook cell outputs and example Ed25519 keys in the HDP agentic-security demo, not real credentials. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5532 lines
199 KiB
Plaintext
5532 lines
199 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"To run this, press \"*Runtime*\" and press \"*Run all*\" on a **free** Tesla T4 Google Colab instance!\n",
|
||
"<div class=\"align-center\">\n",
|
||
"<a href=\"https://unsloth.ai/\"><img src=\"https://github.com/unslothai/unsloth/raw/main/images/unsloth%20new%20logo.png\" width=\"115\"></a>\n",
|
||
"<a href=\"https://discord.gg/unsloth\"><img src=\"https://github.com/unslothai/unsloth/raw/main/images/Discord button.png\" width=\"145\"></a>\n",
|
||
"<a href=\"https://unsloth.ai/docs/\"><img src=\"https://github.com/unslothai/unsloth/blob/main/images/documentation%20green%20button.png?raw=true\" width=\"125\"></a> Join Discord if you need help + ⭐ <i>Star us on <a href=\"https://github.com/unslothai/unsloth\">Github</a> </i> ⭐\n",
|
||
"</div>\n",
|
||
"\n",
|
||
"To install Unsloth on your local device, follow [our guide](https://unsloth.ai/docs/get-started/install). This notebook is licensed [LGPL-3.0](https://github.com/unslothai/notebooks?tab=LGPL-3.0-1-ov-file#readme).\n",
|
||
"\n",
|
||
"You will learn how to do [data prep](#Data), how to [train](#Train), how to [run the model](#Inference), & how to save it"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Installation"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": "%%capture\nimport os, re\nif \"COLAB_\" not in \"\".join(os.environ.keys()):\n !pip install unsloth # Do this in local & cloud setups\nelse:\n import torch; v = re.match(r'[\\d]{1,}\\.[\\d]{1,}', str(torch.__version__)).group(0)\n xformers = 'xformers==' + {'2.10':'0.0.34','2.9':'0.0.33.post1','2.8':'0.0.32.post2'}.get(v, \"0.0.34\")\n !pip install sentencepiece protobuf \"datasets==4.3.0\" \"huggingface_hub>=0.34.0\" hf_transfer\n !pip install --no-deps unsloth_zoo bitsandbytes accelerate {xformers} peft trl triton unsloth\n!pip install --no-deps transformers==5.5.0\n!pip install torchcodec\nimport torch; torch._dynamo.config.recompile_limit = 64;"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": "#@title Colab Extra Install { display-mode: \"form\" }\n%%capture\nimport os\n!pip install --upgrade -qqq uv\nif \"COLAB_\" not in \"\".join(os.environ.keys()):\n # If you're not in Colab, just use pip install!\n !pip install unsloth vllm\nelse:\n try: import numpy, PIL; _numpy = f'numpy=={numpy.__version__}'; _pil = f'pillow=={PIL.__version__}'\n except: _numpy = \"numpy\"; _pil = \"pillow\"\n try: import subprocess; is_t4 = \"Tesla T4\" in str(subprocess.check_output([\"nvidia-smi\"]))\n except: is_t4 = False\n _vllm, _triton = ('vllm==0.9.2', 'triton==3.2.0') if is_t4 else ('vllm==0.15.1', 'triton')\n !uv pip install -qqq --upgrade {_vllm} {_numpy} {_pil} torchvision bitsandbytes xformers unsloth\n !uv pip install -qqq {_triton}\n!uv pip install transformers==4.56.2\n!uv pip install --no-deps trl==0.22.2"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Unsloth"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Goal: Make faster kernels with Reinforcement Learning\n",
|
||
"\n",
|
||
"Our goal is to make a faster matrix multiplication kernel by doing RL on Gemma 4 with Unsloth.\n",
|
||
"\n",
|
||
"<img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Matrix_multiplication_qtl1.svg/500px-Matrix_multiplication_qtl1.svg.png\" height=200 />\n",
|
||
"\n",
|
||
"You will learn how to:\n",
|
||
"1. Counteract **reward hacking** like cheating, caching, laziness.\n",
|
||
"2. Timing and correctness of kernels and time limits.\n",
|
||
"3. Making good **reward functions**\n",
|
||
"4. How to seriously do RL to make optimized kernels"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": [
|
||
"from unsloth import FastVisionModel\n",
|
||
"import torch\n",
|
||
"max_seq_length = 4096 # Can increase for longer reasoning traces\n",
|
||
"lora_rank = 32 # Larger rank = smarter, but slower\n",
|
||
"\n",
|
||
"gemma4_models = [\n",
|
||
" # Gemma-4 instruct models:\n",
|
||
" \"unsloth/gemma-4-E2B-it\",\n",
|
||
" \"unsloth/gemma-4-E4B-it\",\n",
|
||
" \"unsloth/gemma-4-31B-it\",\n",
|
||
" \"unsloth/gemma-4-26B-A4B-it\",\n",
|
||
" # Gemma-4 base models:\n",
|
||
" \"unsloth/gemma-4-E2B\",\n",
|
||
" \"unsloth/gemma-4-E4B\",\n",
|
||
" \"unsloth/gemma-4-31B\",\n",
|
||
" \"unsloth/gemma-4-26B-A4B\",\n",
|
||
"] # More models at https://huggingface.co/unsloth\n",
|
||
"\n",
|
||
"model, tokenizer = FastVisionModel.from_pretrained(\n",
|
||
" model_name = \"unsloth/gemma-4-E2B-it\",\n",
|
||
" max_seq_length = max_seq_length,\n",
|
||
" load_in_4bit = False, # False for LoRA 16bit\n",
|
||
" fast_inference = False, # Enable vllm fast inference\n",
|
||
")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"We now add some small amount of LoRA weights to Gemma 4 so we only need to train those, instead of training on the full model."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": [
|
||
"model = FastVisionModel.get_peft_model(\n",
|
||
" model,\n",
|
||
" r = lora_rank, # Choose any number > 0 ! Suggested 8, 16, 32, 64, 128\n",
|
||
" target_modules = [\n",
|
||
" \"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\",\n",
|
||
" \"gate_proj\", \"up_proj\", \"down_proj\",\n",
|
||
" ],\n",
|
||
" lora_alpha = lora_rank*2, # *2 speeds up training\n",
|
||
" use_gradient_checkpointing = \"unsloth\", # Reduces memory usage\n",
|
||
" random_state = 3407,\n",
|
||
")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Optimized matrix multiplication\n",
|
||
"\n",
|
||
"Numpy has optimized matrix multiplication kernels for CPUs via BLAS optimized operations. For GPUs, one can use CUDA accelerated cuBLAS kernels which PyTorch calls under the hood.\n",
|
||
"\n",
|
||
"To generate some random matrices to do matrix multiplication, we can do the below:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import numpy as np\n",
|
||
"def generate_random_matrices(seed = 3407, n = 256):\n",
|
||
" random_state = np.random.RandomState(seed)\n",
|
||
" n, k, m = random_state.randint(1, n+1, size = 3)\n",
|
||
" A = np.random.uniform(-10, 10, size = (n, k))\n",
|
||
" B = np.random.uniform(-10, 10, size = (k, m))\n",
|
||
" return A, A.tolist(), B, B.tolist()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"We shall generate a small matrix, and see the matrix multiplied output"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"[[-2.8313286 4.54613909 -7.95265309 6.53459836 2.87235103]\n",
|
||
" [ 7.0739631 3.76278879 9.31565599 -8.52884711 9.96832952]\n",
|
||
" [ 8.41214082 6.51136046 -3.79347975 -2.46773693 -2.32292989]\n",
|
||
" [ 3.91302932 4.98335304 -5.33855089 5.71057634 -2.79871647]]\n",
|
||
"[[ 0.39218774 -9.6181377 -3.49736707]\n",
|
||
" [-0.33354865 -1.05626139 3.87231208]\n",
|
||
" [ 0.49494174 5.91863954 -6.83183693]\n",
|
||
" [ 5.1465162 -7.51648113 1.00445384]\n",
|
||
" [ 9.63213377 -4.92327556 3.323014 ]]\n",
|
||
"[[ 54.73441488 -87.89725072 97.94605887]\n",
|
||
" [ 58.25238906 -1.8467447 -49.25453031]\n",
|
||
" [ -35.82528794 -80.25394462 11.51225408]\n",
|
||
" [ -0.33785799 -103.64132345 38.51974367]]\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"A, A_list, B, B_list = generate_random_matrices(seed = 42, n = 5)\n",
|
||
"print(A)\n",
|
||
"print(B)\n",
|
||
"print(np.matmul(A, B))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"We can call a LLM to generate a simple matrix multiply kernel in Python only, and we can calculate the differences between the actual result and the kernel's result"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def calculate_difference(pred, real):\n",
|
||
" if pred is None: return 5, 5\n",
|
||
" assert real is not None\n",
|
||
" import numpy as np\n",
|
||
" try:\n",
|
||
" difference = pred - real\n",
|
||
" except:\n",
|
||
" return 5, 5\n",
|
||
" amax_error = float(np.amax(difference))\n",
|
||
" mse_error = float(np.mean(np.square(difference)))\n",
|
||
" return amax_error, mse_error"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Kernel generated by GPT-5\n",
|
||
"def matmul(A, B):\n",
|
||
" z, s = zip, sum\n",
|
||
" Bt = list(z(*B))\n",
|
||
" return [[s(a*b for a, b in z(row, col)) for col in Bt] for row in A]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"We see the error below is very small, so that's good!"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"(7.105427357601002e-15, 4.6783406255758477e-29)"
|
||
]
|
||
},
|
||
"execution_count": 8,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"prediction = matmul(A_list, B_list)\n",
|
||
"calculate_difference(prediction, np.matmul(A, B))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Countering Reward Hacking\n",
|
||
"\n",
|
||
"The ultimate goal of RL is to maximize some reward (say speed, revenue, some metric).\n",
|
||
"\n",
|
||
"But RL can **cheat** When the RL algorithm learns a trick or exploits something to increase the reward, without actually doing the task at end, this is called \"Reward Hacking\".\n",
|
||
"\n",
|
||
"Some good examples are in https://en.wikipedia.org/wiki/Reward_hacking\n",
|
||
"\n",
|
||
"For matrix multiplication kernels, we might see the following issues:\n",
|
||
"\n",
|
||
"* Laziness: RL learns to use Numpy, Torch, other libraries, which calls optimized kernels.\n",
|
||
"* Caching: RL learns to cache the result of the output\n",
|
||
"* Cheating: RL learns to find the actual output by inspecting Python global variables\n",
|
||
"* RL learns to edit the timing function to make it output 0 time as passed.\n",
|
||
"\n",
|
||
"And possibly more. We shall try to address each!"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Countering Reward Hacking 1: Stop laziness\n",
|
||
"We can stop the RL algorithm from calling optimized code by inspecting if the generated code imports other non standard Python libraries. We used GPT-5 to help generate this check `check_only_stdlib_imports`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"#@title (Collapsible code)\n",
|
||
"import ast\n",
|
||
"import sys\n",
|
||
"import sysconfig\n",
|
||
"from pathlib import Path\n",
|
||
"\n",
|
||
"def _stdlib_names():\n",
|
||
" \"\"\"\n",
|
||
" Build a set of canonical stdlib top-level module/package names.\n",
|
||
" Uses sys.stdlib_module_names when available (3.10+), with a\n",
|
||
" filesystem fallback for older versions/edge cases.\n",
|
||
" \"\"\"\n",
|
||
" names = {m.lower() for m in getattr(sys, \"stdlib_module_names\", set())}\n",
|
||
" names |= {m.lower() for m in sys.builtin_module_names}\n",
|
||
" names.add(\"__future__\") # special-case\n",
|
||
"\n",
|
||
" # Fallback/augmentation: scan the stdlib directory\n",
|
||
" try:\n",
|
||
" stdlib_dir = Path(sysconfig.get_path(\"stdlib\"))\n",
|
||
" if stdlib_dir.exists():\n",
|
||
" for p in stdlib_dir.iterdir():\n",
|
||
" if p.name == \"site-packages\":\n",
|
||
" continue\n",
|
||
" if p.suffix == \".py\":\n",
|
||
" names.add(p.stem.lower())\n",
|
||
" elif p.is_dir() and (p / \"__init__.py\").exists():\n",
|
||
" names.add(p.name.lower())\n",
|
||
" except Exception:\n",
|
||
" # conservative fallback; the names set above will still work well\n",
|
||
" pass\n",
|
||
"\n",
|
||
" return names\n",
|
||
"\n",
|
||
"_STDLIB_SET = _stdlib_names()\n",
|
||
"\n",
|
||
"def check_only_stdlib_imports(code: str):\n",
|
||
" \"\"\"\n",
|
||
" Return (ok: bool, details: dict)\n",
|
||
"\n",
|
||
" ok == True -> all absolute imports are from the stdlib.\n",
|
||
" ok == False -> details['non_stdlib'] lists offending top-level modules.\n",
|
||
"\n",
|
||
" details includes:\n",
|
||
" - stdlib: sorted list of stdlib imports found\n",
|
||
" - non_stdlib: sorted list of non-stdlib imports found\n",
|
||
" - relative_imports: count of relative imports (always allowed here)\n",
|
||
" \"\"\"\n",
|
||
" try:\n",
|
||
" tree = ast.parse(code)\n",
|
||
" except SyntaxError as e:\n",
|
||
" return False, {\n",
|
||
" \"error\": f\"SyntaxError: {e}\",\n",
|
||
" \"stdlib\": [],\n",
|
||
" \"non_stdlib\": [],\n",
|
||
" \"relative_imports\": 0,\n",
|
||
" }\n",
|
||
"\n",
|
||
" abs_imports = set()\n",
|
||
" relative_count = 0\n",
|
||
"\n",
|
||
" class Visitor(ast.NodeVisitor):\n",
|
||
" def visit_Import(self, node: ast.Import):\n",
|
||
" for alias in node.names:\n",
|
||
" abs_imports.add(alias.name.split(\".\")[0])\n",
|
||
" def visit_ImportFrom(self, node: ast.ImportFrom):\n",
|
||
" nonlocal relative_count\n",
|
||
" if (node.level or 0) > 0:\n",
|
||
" # relative import\n",
|
||
" relative_count += 1\n",
|
||
" else:\n",
|
||
" if node.module:\n",
|
||
" abs_imports.add(node.module.split(\".\")[0])\n",
|
||
"\n",
|
||
" Visitor().visit(tree)\n",
|
||
"\n",
|
||
" stdlib_found = sorted(m for m in abs_imports if m.lower() in _STDLIB_SET)\n",
|
||
" non_stdlib = sorted(m for m in abs_imports if m.lower() not in _STDLIB_SET)\n",
|
||
"\n",
|
||
" return len(non_stdlib) == 0, {\n",
|
||
" \"stdlib\": stdlib_found,\n",
|
||
" \"non_stdlib\": non_stdlib,\n",
|
||
" \"relative_imports\": relative_count,\n",
|
||
" }"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"For example, let's call `check_only_stdlib_imports` on a random piece of matrix multiplication code generated by GPT-5:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Only stdlib imports? False\n",
|
||
"{'stdlib': [], 'non_stdlib': ['numpy', 'torch'], 'relative_imports': 0}\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"sample = \"\"\"\n",
|
||
"def matmul(A, B):\n",
|
||
" import numpy as np\n",
|
||
" from torch import matmul\n",
|
||
" z, s = zip, sum\n",
|
||
" Bt = list(z(*B))\n",
|
||
" return [[s(a*b for a, b in z(row, col)) for col in Bt] for row in A]\n",
|
||
"\"\"\"\n",
|
||
"ok, info = check_only_stdlib_imports(sample)\n",
|
||
"print(\"Only stdlib imports?\", ok)\n",
|
||
"print(info)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Countering Reward Hacking 2: Stop cheating\n",
|
||
"We can stop the RL algorithm from using global or cached variables by restricting it's `locals` and `globals`.\n",
|
||
"\n",
|
||
"We are also going to use `exec` to create the function, so we have to save the output to an empty dict.\n",
|
||
"\n",
|
||
"We also disallow global variable access."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"<function matmul(A, B)>"
|
||
]
|
||
},
|
||
"execution_count": 11,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"output_function = {}\n",
|
||
"exec(sample, {}, output_function)\n",
|
||
"output_function[\"matmul\"]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"We also disallow global variable access via `types.FunctionType(f.__code__, {})`"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Success\n",
|
||
"name 'np' is not defined\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"import types\n",
|
||
"output_function[\"matmul\"] = types.FunctionType(output_function[\"matmul\"].__code__, {})\n",
|
||
"\n",
|
||
"def import_numpy():\n",
|
||
" np.matmul\n",
|
||
" print(\"Success\")\n",
|
||
"\n",
|
||
"import_numpy()\n",
|
||
"import_numpy = types.FunctionType(import_numpy.__code__, {})\n",
|
||
"try:\n",
|
||
" import_numpy()\n",
|
||
"except Exception as e:\n",
|
||
" print(str(e))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def create_locked_down_function(function):\n",
|
||
" output_function = {}\n",
|
||
" exec(function, {}, output_function)\n",
|
||
" new_matmul = output_function[\"matmul\"]\n",
|
||
" new_matmul = types.FunctionType(new_matmul.__code__, {})\n",
|
||
" return new_matmul"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Countering Reward Hacking 3: Stop caching\n",
|
||
"We can stop the RL algorithm from using cached data by wiping the cache with a large fake matrix. We also have to benchmark carefully with multiple loops and turns.\n",
|
||
"\n",
|
||
"We also add a **timer** to not make the algorithm go in an endless loop."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import os, gc, time, statistics\n",
|
||
"import signal\n",
|
||
"from contextlib import contextmanager\n",
|
||
"class TimeoutError(Exception): pass\n",
|
||
"\n",
|
||
"@contextmanager\n",
|
||
"def time_limit(seconds):\n",
|
||
" def _handler(signum, frame):\n",
|
||
" raise TimeoutError(f\"Timed out after {seconds}s\")\n",
|
||
" old = signal.signal(signal.SIGALRM, _handler)\n",
|
||
" signal.setitimer(signal.ITIMER_REAL, seconds)\n",
|
||
" try:\n",
|
||
" yield\n",
|
||
" finally:\n",
|
||
" signal.setitimer(signal.ITIMER_REAL, 0.0)\n",
|
||
" signal.signal(signal.SIGALRM, old)\n",
|
||
"\n",
|
||
"class Benchmarker:\n",
|
||
" def __init__(self, trials = 3, loops = 1, timeout = 30):\n",
|
||
" self.buffer = np.zeros(2 * 1024 * 1024 * 1024, dtype = np.uint8)\n",
|
||
" self.trials = trials\n",
|
||
" self.loops = loops\n",
|
||
" assert timeout > 0 # Cannot be 0 since it won't work!\n",
|
||
" self.timeout = timeout\n",
|
||
" def thrash(self):\n",
|
||
" # Edit the buffer to wipe cache lines\n",
|
||
" self.buffer ^= 1\n",
|
||
" return int(self.buffer[::4096].sum())\n",
|
||
"\n",
|
||
" def benchmark(self, function, arguments):\n",
|
||
" assert len(arguments) == self.loops\n",
|
||
" samples = []\n",
|
||
" exceptions = []\n",
|
||
" timed_out = 0\n",
|
||
" for _ in range(self.trials):\n",
|
||
" gc.collect(); gc.disable(); self.thrash()\n",
|
||
" t_start = time.perf_counter_ns()\n",
|
||
" for i in range(self.loops):\n",
|
||
" try:\n",
|
||
" with time_limit(self.timeout):\n",
|
||
" function(*arguments[i])\n",
|
||
" except TimeoutError as e:\n",
|
||
" timed_out += 1\n",
|
||
" except Exception as e:\n",
|
||
" exceptions.append(str(e))\n",
|
||
" t_end = time.perf_counter_ns()\n",
|
||
" gc.enable()\n",
|
||
" samples.append((t_end - t_start) // max(1, self.loops))\n",
|
||
" return {\n",
|
||
" \"median_ns\": int(statistics.median(samples)),\n",
|
||
" \"mean_ns\": int(statistics.fmean(samples)),\n",
|
||
" \"stdev_ns\": int(statistics.pstdev(samples) if len(samples) > 1 else 0),\n",
|
||
" \"exceptions\" : exceptions,\n",
|
||
" \"timeouts\" : timed_out,\n",
|
||
" }"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"For example we use our matmul kernel we had, and benchmark it with a 10 second delay:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"{'median_ns': 70895404,\n",
|
||
" 'mean_ns': 70895404,\n",
|
||
" 'stdev_ns': 0,\n",
|
||
" 'exceptions': [],\n",
|
||
" 'timeouts': 0}"
|
||
]
|
||
},
|
||
"execution_count": 15,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"A, A_list, B, B_list = generate_random_matrices(seed = 0, n = 256)\n",
|
||
"Benchmarker(trials = 1, timeout = 10).benchmark(output_function[\"matmul\"], [(A_list, B_list)])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Data & RL task setup\n",
|
||
"\n",
|
||
"We now have to create a prompt to the model for which it will do some task. For our matrix multiply example, we use the below:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Create a new fast matrix multiplication function using only native Python code.\n",
|
||
"You are given a list of list of numbers.\n",
|
||
"Output your new function in backticks using the format below:\n",
|
||
"```python\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"```\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"prompt = \"\"\"\n",
|
||
"Create a new fast matrix multiplication function using only native Python code.\n",
|
||
"You are given a list of list of numbers.\n",
|
||
"Output your new function in backticks using the format below:\n",
|
||
"```python\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"```\n",
|
||
"\"\"\".strip()\n",
|
||
"print(prompt)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"First, let's prompt Gemma 4 without RL and see how it goes:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": [
|
||
"text = tokenizer.apply_chat_template(\n",
|
||
" [{\"role\": \"user\", \"content\": prompt.strip()}],\n",
|
||
" tokenize = False,\n",
|
||
" add_generation_prompt = True,\n",
|
||
")\n",
|
||
"\n",
|
||
"from transformers import TextStreamer\n",
|
||
"print(\"=\" * 50)\n",
|
||
"print(\"BASE MODEL OUTPUT (before RL training):\")\n",
|
||
"print(\"=\" * 50)\n",
|
||
"\n",
|
||
"inputs = tokenizer(\n",
|
||
" text = text,\n",
|
||
" add_special_tokens = False,\n",
|
||
" return_tensors = \"pt\",\n",
|
||
").to(\"cuda\")\n",
|
||
"\n",
|
||
"text_streamer = TextStreamer(tokenizer, skip_prompt = True)\n",
|
||
"result = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 512,\n",
|
||
" use_cache = True, temperature = 1.0, top_p = 0.95, top_k = 64)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Reward functions\n",
|
||
"\n",
|
||
"We now design the `extract_function` function which simply extracts the function wrapped in 3 backticks.\n",
|
||
"\n",
|
||
"And 4 reward functions:\n",
|
||
"\n",
|
||
"1. `function_works` which rewards the model if the strategy is a valid Python function.\n",
|
||
"2. `no_cheating` which checks if the function imported other modules, and if it did, we penalize it.\n",
|
||
"3. `correctness_check` which checks if the kernel was correct or wrong - it shouldn't generate gibberish!\n",
|
||
"4. `speed_check` checks the performance relative to Numpy matmul directly."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"def matmul(A, B):\n",
|
||
" return ...\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"def extract_function(text):\n",
|
||
" if text.count(\"```\") >= 2:\n",
|
||
" first = text.find(\"```\") + 3\n",
|
||
" second = text.find(\"```\", first)\n",
|
||
" fx = text[first : second].strip()\n",
|
||
" fx = fx.removeprefix(\"python\\n\")\n",
|
||
" fx = fx[fx.find(\"def\"):]\n",
|
||
" if fx.startswith(\"def matmul(A, B):\"): return fx\n",
|
||
" return None\n",
|
||
"print(extract_function(prompt))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Below is our `function_works` reward function which uses Python's `exec` but guarded by not allowing leakage of local and global variables. We can also use `check_only_stdlib_imports` first to check if there are errors before even executing the function:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"(False,\n",
|
||
" {'error': \"SyntaxError: expected '(' (<unknown>, line 1)\",\n",
|
||
" 'stdlib': [],\n",
|
||
" 'non_stdlib': [],\n",
|
||
" 'relative_imports': 0})"
|
||
],
|
||
"text/html": [
|
||
"<pre>(False,\n",
|
||
" {'error': "SyntaxError: expected '(' (<unknown>, line 1)",\n",
|
||
" 'stdlib': [],\n",
|
||
" 'non_stdlib': [],\n",
|
||
" 'relative_imports': 0})</pre>"
|
||
]
|
||
},
|
||
"execution_count": 19,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"ok, info = check_only_stdlib_imports(\"def a\")\n",
|
||
"ok, info"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def function_works(completions, **kwargs):\n",
|
||
" scores = []\n",
|
||
" for completion in completions:\n",
|
||
" score = 0\n",
|
||
" response = completion[0][\"content\"]\n",
|
||
" function = extract_function(response)\n",
|
||
" print(function)\n",
|
||
" if function is not None:\n",
|
||
" ok, info = check_only_stdlib_imports(function)\n",
|
||
" if function is None or \"error\" in info:\n",
|
||
" score = -2.0\n",
|
||
" else:\n",
|
||
" try:\n",
|
||
" new_matmul = create_locked_down_function(function)\n",
|
||
" score = 1.0\n",
|
||
" except:\n",
|
||
" score = -0.5\n",
|
||
" scores.append(score)\n",
|
||
" return scores"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"`no_cheating` checks if the function cheated since it might have imported Numpy or Torch optimized code."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def no_cheating(completions, **kwargs):\n",
|
||
" scores = []\n",
|
||
" for completion in completions:\n",
|
||
" score = 0\n",
|
||
" response = completion[0][\"content\"]\n",
|
||
" function = extract_function(response)\n",
|
||
" if function is not None:\n",
|
||
" ok, info = check_only_stdlib_imports(function)\n",
|
||
" else:\n",
|
||
" ok = False\n",
|
||
" scores.append(1.0 if ok else -20.0) # Penalize heavily!\n",
|
||
" return scores"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Next `correctness_check` checks if the kernel was correct. We want to penalize if the absolute error is larger than 1, and if the mean squared error is somewhat bigger then machine epsilon.\n",
|
||
"\n",
|
||
"We have to execute the code now!"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"np.float64(2.220446049250313e-16)"
|
||
]
|
||
},
|
||
"execution_count": 22,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"np.finfo(np.float64).eps"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def correctness_check(completions, **kwargs):\n",
|
||
" scores = []\n",
|
||
" # Generate some random matrices of size less than 128\n",
|
||
" A, A_list, B, B_list = generate_random_matrices(seed = np.random.randint(10000), n = 128)\n",
|
||
" for completion in completions:\n",
|
||
" score = 0\n",
|
||
" response = completion[0][\"content\"]\n",
|
||
" function = extract_function(response)\n",
|
||
" if function is not None:\n",
|
||
" ok, info = check_only_stdlib_imports(function)\n",
|
||
" if function is None or \"error\" in info:\n",
|
||
" scores.append(0)\n",
|
||
" continue\n",
|
||
" try:\n",
|
||
" new_matmul = create_locked_down_function(function)\n",
|
||
" except:\n",
|
||
" scores.append(0)\n",
|
||
" continue\n",
|
||
" try:\n",
|
||
" pred = new_matmul(A_list.copy(), B_list.copy())\n",
|
||
" except:\n",
|
||
" # Failed!\n",
|
||
" scores.append(-2.0)\n",
|
||
" continue\n",
|
||
" true = np.matmul(A, B)\n",
|
||
" amax_error, mse_error = calculate_difference(pred, true)\n",
|
||
"\n",
|
||
" # Check correctness and score!\n",
|
||
" machine_epsilon = 100*np.finfo(np.float64).eps\n",
|
||
" if amax_error >= 3: score = -3.0\n",
|
||
" elif amax_error >= 2: score = -2.5\n",
|
||
" elif amax_error >= 1: score = -2.0\n",
|
||
" elif amax_error >= 0.5: score = -1.0\n",
|
||
" elif amax_error >= 100*machine_epsilon: score = 0.0\n",
|
||
" elif amax_error >= machine_epsilon: score = 1.0\n",
|
||
" else: score = 3.0\n",
|
||
"\n",
|
||
" if mse_error >= 3: score += -3.0\n",
|
||
" elif mse_error >= 2: score += -2.5\n",
|
||
" elif mse_error >= 1: score += -2.0\n",
|
||
" elif mse_error >= 0.5: score += -1.0\n",
|
||
" elif mse_error >= 100*machine_epsilon: score += 0.0\n",
|
||
" elif mse_error >= machine_epsilon: score += 1.0\n",
|
||
" else: score += 3.0\n",
|
||
" scores.append(score)\n",
|
||
" return scores"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Finally our benchmarking function for `speed_check`! We shall limit the timer to 10 seconds and do 3 trials."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"{'median_ns': 205566,\n",
|
||
" 'mean_ns': 231173,\n",
|
||
" 'stdev_ns': 39247,\n",
|
||
" 'exceptions': [],\n",
|
||
" 'timeouts': 0}"
|
||
]
|
||
},
|
||
"execution_count": 24,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"A, A_list, B, B_list = generate_random_matrices(seed = 0, n = 256)\n",
|
||
"benchmarker = Benchmarker(trials = 3, timeout = 10)\n",
|
||
"numpy_results = benchmarker.benchmark(np.matmul, [(A, B)])\n",
|
||
"numpy_results"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"{'median_ns': 84237,\n",
|
||
" 'mean_ns': 87442,\n",
|
||
" 'stdev_ns': 4538,\n",
|
||
" 'exceptions': [],\n",
|
||
" 'timeouts': 0}"
|
||
]
|
||
},
|
||
"execution_count": 25,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"new_matmul = create_locked_down_function(extract_function(prompt))\n",
|
||
"new_results = benchmarker.benchmark(new_matmul, [(A_list, B_list)])\n",
|
||
"new_results"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"We can take the difference and do a negative sign for slower ones. If the ratio is less than 1 (ie faster, we shall invert it!)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"0.02440329071548132"
|
||
]
|
||
},
|
||
"execution_count": 26,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"negative = -(new_results[\"median_ns\"] / numpy_results[\"median_ns\"]) / 100\n",
|
||
"positive = +(numpy_results[\"median_ns\"] / new_results[\"median_ns\"]) / 100\n",
|
||
"reward = negative if new_results[\"median_ns\"] >= numpy_results[\"median_ns\"] else positive\n",
|
||
"reward"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"3.333333333333333"
|
||
]
|
||
},
|
||
"execution_count": 27,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"new_results[\"median_ns\"] = 3\n",
|
||
"numpy_results[\"median_ns\"] = 1000\n",
|
||
"negative = -(new_results[\"median_ns\"] / numpy_results[\"median_ns\"]) / 100\n",
|
||
"positive = +(numpy_results[\"median_ns\"] / new_results[\"median_ns\"]) / 100\n",
|
||
"reward = negative if new_results[\"median_ns\"] >= numpy_results[\"median_ns\"] else positive\n",
|
||
"reward"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import gc\n",
|
||
"def speed_check(completions, **kwargs):\n",
|
||
" scores = []\n",
|
||
" # Generate some random matrices of size less than 256\n",
|
||
" A, A_list, B, B_list = generate_random_matrices(seed = np.random.randint(10000), n = 256)\n",
|
||
" numpy_results = benchmarker.benchmark(np.matmul, [(A, B)])\n",
|
||
" for completion in completions:\n",
|
||
" score = 0\n",
|
||
" response = completion[0][\"content\"]\n",
|
||
" function = extract_function(response)\n",
|
||
" if function is not None:\n",
|
||
" ok, info = check_only_stdlib_imports(function)\n",
|
||
" if function is None or \"error\" in info:\n",
|
||
" scores.append(0)\n",
|
||
" continue\n",
|
||
" try:\n",
|
||
" new_matmul = create_locked_down_function(function)\n",
|
||
" except:\n",
|
||
" scores.append(0)\n",
|
||
" continue\n",
|
||
" new_results = benchmarker.benchmark(new_matmul, [(A_list.copy(), B_list.copy())])\n",
|
||
"\n",
|
||
" # Get score and clip to -10, 10\n",
|
||
" negative = -(new_results[\"median_ns\"] / numpy_results[\"median_ns\"]) / 100\n",
|
||
" positive = +(numpy_results[\"median_ns\"] / new_results[\"median_ns\"]) / 100\n",
|
||
" score = negative if new_results[\"median_ns\"] >= numpy_results[\"median_ns\"] else positive\n",
|
||
" if score >= 10: score = 10\n",
|
||
" if score <= -10: score = -10\n",
|
||
" scores.append(score)\n",
|
||
" # Free memory to counteract OOMs\n",
|
||
" gc.collect()\n",
|
||
" torch.cuda.empty_cache()\n",
|
||
" return scores"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"We create the dataset which includes a replica of our prompt."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": [
|
||
"from datasets import Dataset\n",
|
||
"dataset = Dataset.from_list([{\"prompt\" : [{\"role\": \"user\", \"content\": prompt.strip()}], \"answer\" : 0}]*1000)\n",
|
||
"maximum_length = len(tokenizer.apply_chat_template([{\"role\":\"user\", \"content\":prompt.strip()}], add_generation_prompt = True, tokenize = True))\n",
|
||
"print(maximum_length)\n",
|
||
"dataset[0]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<a name=\"Train\"></a>\n",
|
||
"### Train the model\n",
|
||
"\n",
|
||
"Now set up GRPO Trainer and all configurations! We also support GSDP, GAPO, Dr GRPO and more! Go to our docs https://unsloth.ai/docs/ for more info!"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": [
|
||
"# Leave room for the prompt (plus 1 token safety margin)\n",
|
||
"max_completion_length = max_seq_length - (maximum_length + 1)\n",
|
||
"\n",
|
||
"from trl import GRPOConfig, GRPOTrainer\n",
|
||
"training_args = GRPOConfig(\n",
|
||
" temperature = 1.0,\n",
|
||
" top_p = 0.95,\n",
|
||
" top_k = 64,\n",
|
||
" learning_rate = 5e-5,\n",
|
||
" weight_decay = 0.001,\n",
|
||
" warmup_ratio = 0.1,\n",
|
||
" lr_scheduler_type = \"linear\",\n",
|
||
" optim = \"adamw_8bit\",\n",
|
||
" logging_steps = 1,\n",
|
||
" per_device_train_batch_size = 1,\n",
|
||
" gradient_accumulation_steps = 2, # Increase to 4 for smoother training\n",
|
||
" num_generations = 2, # Decrease if out of memory\n",
|
||
" max_completion_length = max_completion_length,\n",
|
||
" # num_train_epochs = 1, # Set to 1 for a full training run\n",
|
||
" max_steps = 100,\n",
|
||
" save_steps = 100,\n",
|
||
" report_to = \"none\", # Can use Weights & Biases, TrackIO\n",
|
||
" output_dir = \"outputs\",\n",
|
||
" epsilon = 0.2,\n",
|
||
" epsilon_high = 0.28, # one sided\n",
|
||
" delta = 1.5, # two sided\n",
|
||
" loss_type = 'bnpo',\n",
|
||
" mask_truncated_completions = True\n",
|
||
" # For optional training + evaluation\n",
|
||
" # fp16_full_eval = True,\n",
|
||
" # per_device_eval_batch_size = 4,\n",
|
||
" # eval_accumulation_steps = 1,\n",
|
||
" # eval_strategy = \"steps\",\n",
|
||
" # eval_steps = 1,\n",
|
||
")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"And let's run the trainer! If you scroll up, you'll see a table of rewards. The goal is to see the `reward` column increase!\n",
|
||
"\n",
|
||
"You might have to wait 150 to 200 steps for any action. You'll probably get 0 reward for the first 100 steps. Please be patient!\n",
|
||
"\n",
|
||
"| Step | Training Loss | reward | reward_std | completion_length | kl |\n",
|
||
"|------|---------------|-----------|------------|-------------------|----------|\n",
|
||
"| 1 | 0.000000 | 0.125000 | 0.000000 | 200.000000 | 0.000000 |\n",
|
||
"| 2 | 0.000000 | 0.072375 | 0.248112 | 200.000000 | 0.000000 |\n",
|
||
"| 3 | 0.000000 | -0.079000 | 0.163776 | 182.500000 | 0.000005 |"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# For optional training + evaluation\n",
|
||
"# new_dataset = dataset.train_test_split(test_size = 0.01)\n",
|
||
"\n",
|
||
"trainer = GRPOTrainer(\n",
|
||
" model = model,\n",
|
||
" processing_class = tokenizer,\n",
|
||
" reward_funcs = [\n",
|
||
" function_works,\n",
|
||
" no_cheating,\n",
|
||
" correctness_check,\n",
|
||
" speed_check,\n",
|
||
" ],\n",
|
||
" args = training_args,\n",
|
||
" train_dataset = dataset,\n",
|
||
"\n",
|
||
" # For optional training + evaluation\n",
|
||
" # train_dataset = new_dataset[\"train\"],\n",
|
||
" # eval_dataset = new_dataset[\"test\"],\n",
|
||
")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"And let's train the model!\n",
|
||
"\n",
|
||
"**NOTE** A T4 free GPU might take 5 minutes for one generation sadly since it's an old GPU - A100 or H100 will be much faster!"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"The tokenizer has new PAD/BOS/EOS tokens that differ from the model config and generation config. The model config and generation config were aligned accordingly, being updated with the tokenizer's values. Updated tokens: {'bos_token_id': 199998}.\n",
|
||
"==((====))== Unsloth - 2x faster free finetuning | Num GPUs used = 1\n",
|
||
" \\\\ /| Num examples = 1,000 | Num Epochs = 1 | Total steps = 100\n",
|
||
"O^O/ \\_/ \\ Batch size per device = 2 | Gradient accumulation steps = 1\n",
|
||
"\\ / Data Parallel GPUs = 1 | Total batch size (2 x 1 x 1) = 2\n",
|
||
" \"-____-\" Trainable parameters = 1,990,656 of 20,916,747,840 (0.01% trained)\n",
|
||
"`generation_config` default values have been modified to match model-specific defaults: {'max_length': 131072}. If this is not desired, please set these values explicitly.\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Fast matrix multiplication using only native Python code.\n",
|
||
" \n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list of list of numbers\n",
|
||
" Left matrix of dimensions (m x p).\n",
|
||
" B : list of list of numbers\n",
|
||
" Right matrix of dimensions (p x n).\n",
|
||
" \n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" C : list of list of numbers\n",
|
||
" Resulting matrix of dimensions (m x n) such that C = A × B.\n",
|
||
" \"\"\"\n",
|
||
" # Transpose B to allow column access as rows.\n",
|
||
" Bt = list(zip(*B))\n",
|
||
" # Compute the dot product of each row from A with each column from B\n",
|
||
" return [[sum(a * b for a, b in zip(row, col))\n",
|
||
" for col in Bt]\n",
|
||
" for row in A]\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/html": [
|
||
"\n",
|
||
" <div>\n",
|
||
" \n",
|
||
" <progress value='100' max='100' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
|
||
" [100/100 1:36:19, Epoch 0/1]\n",
|
||
" </div>\n",
|
||
" <table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: left;\">\n",
|
||
" <th>Step</th>\n",
|
||
" <th>Training Loss</th>\n",
|
||
" <th>reward</th>\n",
|
||
" <th>reward_std</th>\n",
|
||
" <th>completions / mean_length</th>\n",
|
||
" <th>completions / min_length</th>\n",
|
||
" <th>completions / max_length</th>\n",
|
||
" <th>completions / clipped_ratio</th>\n",
|
||
" <th>completions / mean_terminated_length</th>\n",
|
||
" <th>completions / min_terminated_length</th>\n",
|
||
" <th>completions / max_terminated_length</th>\n",
|
||
" <th>kl</th>\n",
|
||
" <th>rewards / function_works / mean</th>\n",
|
||
" <th>rewards / function_works / std</th>\n",
|
||
" <th>rewards / no_cheating / mean</th>\n",
|
||
" <th>rewards / no_cheating / std</th>\n",
|
||
" <th>rewards / correctness_check / mean</th>\n",
|
||
" <th>rewards / correctness_check / std</th>\n",
|
||
" <th>rewards / speed_check / mean</th>\n",
|
||
" <th>rewards / speed_check / std</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <td>1</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-0.960532</td>\n",
|
||
" <td>4.244743</td>\n",
|
||
" <td>536.000000</td>\n",
|
||
" <td>392.000000</td>\n",
|
||
" <td>680.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>536.000000</td>\n",
|
||
" <td>392.000000</td>\n",
|
||
" <td>680.000000</td>\n",
|
||
" <td>0.002798</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-1.960532</td>\n",
|
||
" <td>2.826324</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>2</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-11.504601</td>\n",
|
||
" <td>14.842735</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000834</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-3.504601</td>\n",
|
||
" <td>4.956255</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>3</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.232768</td>\n",
|
||
" <td>3.847022</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000691</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-2.232768</td>\n",
|
||
" <td>3.224046</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>4</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-9.112391</td>\n",
|
||
" <td>18.225832</td>\n",
|
||
" <td>541.000000</td>\n",
|
||
" <td>364.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>364.000000</td>\n",
|
||
" <td>364.000000</td>\n",
|
||
" <td>364.000000</td>\n",
|
||
" <td>0.004645</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-1.112391</td>\n",
|
||
" <td>1.573158</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>5</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.982523</td>\n",
|
||
" <td>0.584465</td>\n",
|
||
" <td>503.000000</td>\n",
|
||
" <td>352.000000</td>\n",
|
||
" <td>654.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>503.000000</td>\n",
|
||
" <td>352.000000</td>\n",
|
||
" <td>654.000000</td>\n",
|
||
" <td>0.004241</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-4.017477</td>\n",
|
||
" <td>0.584465</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>6</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-8.959490</td>\n",
|
||
" <td>18.442066</td>\n",
|
||
" <td>629.500000</td>\n",
|
||
" <td>541.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>541.000000</td>\n",
|
||
" <td>541.000000</td>\n",
|
||
" <td>541.000000</td>\n",
|
||
" <td>0.002716</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.959490</td>\n",
|
||
" <td>1.356924</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>7</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>5.517008</td>\n",
|
||
" <td>0.094176</td>\n",
|
||
" <td>440.500000</td>\n",
|
||
" <td>394.000000</td>\n",
|
||
" <td>487.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>440.500000</td>\n",
|
||
" <td>394.000000</td>\n",
|
||
" <td>487.000000</td>\n",
|
||
" <td>0.001769</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-0.482992</td>\n",
|
||
" <td>0.094176</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>8</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-9.263465</td>\n",
|
||
" <td>18.012180</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000987</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-1.263465</td>\n",
|
||
" <td>1.786810</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>9</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-13.000000</td>\n",
|
||
" <td>12.727922</td>\n",
|
||
" <td>586.000000</td>\n",
|
||
" <td>454.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>454.000000</td>\n",
|
||
" <td>454.000000</td>\n",
|
||
" <td>454.000000</td>\n",
|
||
" <td>0.002943</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-5.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>10</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-3.985678</td>\n",
|
||
" <td>0.000226</td>\n",
|
||
" <td>635.500000</td>\n",
|
||
" <td>553.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>553.000000</td>\n",
|
||
" <td>553.000000</td>\n",
|
||
" <td>553.000000</td>\n",
|
||
" <td>0.001814</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-6.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.014322</td>\n",
|
||
" <td>0.000225</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>11</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-8.366700</td>\n",
|
||
" <td>19.280397</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001235</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.366700</td>\n",
|
||
" <td>0.518593</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>12</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-9.327222</td>\n",
|
||
" <td>17.922014</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000735</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-1.327222</td>\n",
|
||
" <td>1.876975</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>13</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.989250</td>\n",
|
||
" <td>12.743125</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001106</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.010750</td>\n",
|
||
" <td>0.015203</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>14</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.785522</td>\n",
|
||
" <td>2.598972</td>\n",
|
||
" <td>640.500000</td>\n",
|
||
" <td>563.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>563.000000</td>\n",
|
||
" <td>563.000000</td>\n",
|
||
" <td>563.000000</td>\n",
|
||
" <td>0.003206</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>-1.214478</td>\n",
|
||
" <td>1.643669</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>15</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-9.018981</td>\n",
|
||
" <td>18.357933</td>\n",
|
||
" <td>603.000000</td>\n",
|
||
" <td>488.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>488.000000</td>\n",
|
||
" <td>488.000000</td>\n",
|
||
" <td>488.000000</td>\n",
|
||
" <td>0.006529</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-1.018981</td>\n",
|
||
" <td>1.441056</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>16</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-3.985248</td>\n",
|
||
" <td>0.000232</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000625</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-6.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.014752</td>\n",
|
||
" <td>0.000231</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>17</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-8.496688</td>\n",
|
||
" <td>19.096567</td>\n",
|
||
" <td>625.500000</td>\n",
|
||
" <td>533.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>533.000000</td>\n",
|
||
" <td>533.000000</td>\n",
|
||
" <td>533.000000</td>\n",
|
||
" <td>0.003519</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.496688</td>\n",
|
||
" <td>0.702423</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>18</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.985329</td>\n",
|
||
" <td>12.748671</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001027</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.014671</td>\n",
|
||
" <td>0.020748</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>19</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.173172</td>\n",
|
||
" <td>3.936521</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001025</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-2.173172</td>\n",
|
||
" <td>3.134547</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>20</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>391.000000</td>\n",
|
||
" <td>297.000000</td>\n",
|
||
" <td>485.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>391.000000</td>\n",
|
||
" <td>297.000000</td>\n",
|
||
" <td>485.000000</td>\n",
|
||
" <td>0.005021</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>6.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-10.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>21</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-0.387958</td>\n",
|
||
" <td>5.063533</td>\n",
|
||
" <td>593.500000</td>\n",
|
||
" <td>469.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>469.000000</td>\n",
|
||
" <td>469.000000</td>\n",
|
||
" <td>469.000000</td>\n",
|
||
" <td>0.004264</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-1.387958</td>\n",
|
||
" <td>2.007535</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>22</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.992634</td>\n",
|
||
" <td>12.738339</td>\n",
|
||
" <td>524.500000</td>\n",
|
||
" <td>331.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>331.000000</td>\n",
|
||
" <td>331.000000</td>\n",
|
||
" <td>331.000000</td>\n",
|
||
" <td>0.005515</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.007366</td>\n",
|
||
" <td>0.010417</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>23</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000955</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>24</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.989729</td>\n",
|
||
" <td>12.742447</td>\n",
|
||
" <td>635.000000</td>\n",
|
||
" <td>552.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>552.000000</td>\n",
|
||
" <td>552.000000</td>\n",
|
||
" <td>552.000000</td>\n",
|
||
" <td>0.002888</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.010271</td>\n",
|
||
" <td>0.014526</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>25</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001271</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>26</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001055</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>27</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-9.105782</td>\n",
|
||
" <td>18.235178</td>\n",
|
||
" <td>534.000000</td>\n",
|
||
" <td>350.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>350.000000</td>\n",
|
||
" <td>350.000000</td>\n",
|
||
" <td>350.000000</td>\n",
|
||
" <td>0.021608</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-1.105782</td>\n",
|
||
" <td>1.563811</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>28</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>2.792898</td>\n",
|
||
" <td>3.932606</td>\n",
|
||
" <td>645.500000</td>\n",
|
||
" <td>573.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>573.000000</td>\n",
|
||
" <td>573.000000</td>\n",
|
||
" <td>573.000000</td>\n",
|
||
" <td>0.006835</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>-0.207102</td>\n",
|
||
" <td>0.310035</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>29</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-3.970244</td>\n",
|
||
" <td>0.000759</td>\n",
|
||
" <td>616.500000</td>\n",
|
||
" <td>515.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>515.000000</td>\n",
|
||
" <td>515.000000</td>\n",
|
||
" <td>515.000000</td>\n",
|
||
" <td>0.011646</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-6.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.029756</td>\n",
|
||
" <td>0.000759</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>30</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.977889</td>\n",
|
||
" <td>12.759192</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001129</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.022111</td>\n",
|
||
" <td>0.031270</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>31</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.983095</td>\n",
|
||
" <td>12.751829</td>\n",
|
||
" <td>586.500000</td>\n",
|
||
" <td>455.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>455.000000</td>\n",
|
||
" <td>455.000000</td>\n",
|
||
" <td>455.000000</td>\n",
|
||
" <td>0.032435</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.016905</td>\n",
|
||
" <td>0.023908</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>32</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-8.083347</td>\n",
|
||
" <td>19.681118</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001218</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.083347</td>\n",
|
||
" <td>0.117870</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>33</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001185</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>34</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>577.500000</td>\n",
|
||
" <td>477.000000</td>\n",
|
||
" <td>678.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>577.500000</td>\n",
|
||
" <td>477.000000</td>\n",
|
||
" <td>678.000000</td>\n",
|
||
" <td>0.021551</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-10.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>35</td>\n",
|
||
" <td>-0.000000</td>\n",
|
||
" <td>3.214173</td>\n",
|
||
" <td>0.016615</td>\n",
|
||
" <td>609.500000</td>\n",
|
||
" <td>577.000000</td>\n",
|
||
" <td>642.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>609.500000</td>\n",
|
||
" <td>577.000000</td>\n",
|
||
" <td>642.000000</td>\n",
|
||
" <td>0.004937</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-2.785827</td>\n",
|
||
" <td>0.016615</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>36</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001002</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>37</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-8.405643</td>\n",
|
||
" <td>19.225323</td>\n",
|
||
" <td>691.000000</td>\n",
|
||
" <td>664.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>664.000000</td>\n",
|
||
" <td>664.000000</td>\n",
|
||
" <td>664.000000</td>\n",
|
||
" <td>0.001766</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.405643</td>\n",
|
||
" <td>0.573666</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>38</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>2.510188</td>\n",
|
||
" <td>0.017700</td>\n",
|
||
" <td>601.000000</td>\n",
|
||
" <td>541.000000</td>\n",
|
||
" <td>661.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>601.000000</td>\n",
|
||
" <td>541.000000</td>\n",
|
||
" <td>661.000000</td>\n",
|
||
" <td>0.006895</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-3.489812</td>\n",
|
||
" <td>0.017700</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>39</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.143930</td>\n",
|
||
" <td>1.851457</td>\n",
|
||
" <td>676.000000</td>\n",
|
||
" <td>634.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>634.000000</td>\n",
|
||
" <td>634.000000</td>\n",
|
||
" <td>634.000000</td>\n",
|
||
" <td>0.003330</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>-1.856070</td>\n",
|
||
" <td>2.391184</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>40</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.305945</td>\n",
|
||
" <td>0.040185</td>\n",
|
||
" <td>385.500000</td>\n",
|
||
" <td>260.000000</td>\n",
|
||
" <td>511.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>385.500000</td>\n",
|
||
" <td>260.000000</td>\n",
|
||
" <td>511.000000</td>\n",
|
||
" <td>0.021996</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-5.694055</td>\n",
|
||
" <td>0.040185</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>41</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-2.385927</td>\n",
|
||
" <td>0.019569</td>\n",
|
||
" <td>435.000000</td>\n",
|
||
" <td>378.000000</td>\n",
|
||
" <td>492.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>435.000000</td>\n",
|
||
" <td>378.000000</td>\n",
|
||
" <td>492.000000</td>\n",
|
||
" <td>0.004062</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-8.385927</td>\n",
|
||
" <td>0.019569</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>42</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-3.964993</td>\n",
|
||
" <td>0.000042</td>\n",
|
||
" <td>625.000000</td>\n",
|
||
" <td>532.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>532.000000</td>\n",
|
||
" <td>532.000000</td>\n",
|
||
" <td>532.000000</td>\n",
|
||
" <td>0.007571</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-6.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.035007</td>\n",
|
||
" <td>0.000042</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>43</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001561</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>44</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-3.956534</td>\n",
|
||
" <td>0.000491</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001198</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-6.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.043466</td>\n",
|
||
" <td>0.000490</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>45</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-3.973095</td>\n",
|
||
" <td>0.000793</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001338</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-6.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.026904</td>\n",
|
||
" <td>0.000793</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>46</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-3.976156</td>\n",
|
||
" <td>0.033721</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001170</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-4.976156</td>\n",
|
||
" <td>7.104789</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>47</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-0.779847</td>\n",
|
||
" <td>0.030023</td>\n",
|
||
" <td>598.000000</td>\n",
|
||
" <td>478.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>478.000000</td>\n",
|
||
" <td>478.000000</td>\n",
|
||
" <td>478.000000</td>\n",
|
||
" <td>0.003763</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-6.779847</td>\n",
|
||
" <td>0.030023</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>48</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-0.400116</td>\n",
|
||
" <td>5.054048</td>\n",
|
||
" <td>587.000000</td>\n",
|
||
" <td>544.000000</td>\n",
|
||
" <td>630.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>587.000000</td>\n",
|
||
" <td>544.000000</td>\n",
|
||
" <td>630.000000</td>\n",
|
||
" <td>0.002484</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-1.400116</td>\n",
|
||
" <td>2.017020</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>49</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-0.343705</td>\n",
|
||
" <td>5.124783</td>\n",
|
||
" <td>487.000000</td>\n",
|
||
" <td>256.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>256.000000</td>\n",
|
||
" <td>256.000000</td>\n",
|
||
" <td>256.000000</td>\n",
|
||
" <td>0.020560</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-1.343706</td>\n",
|
||
" <td>1.946285</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.349097</td>\n",
|
||
" <td>6.115803</td>\n",
|
||
" <td>524.000000</td>\n",
|
||
" <td>330.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>330.000000</td>\n",
|
||
" <td>330.000000</td>\n",
|
||
" <td>330.000000</td>\n",
|
||
" <td>0.011521</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-0.650903</td>\n",
|
||
" <td>0.955265</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>51</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-3.959916</td>\n",
|
||
" <td>0.001149</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001324</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-6.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.040084</td>\n",
|
||
" <td>0.001149</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>52</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-0.386721</td>\n",
|
||
" <td>5.073168</td>\n",
|
||
" <td>651.000000</td>\n",
|
||
" <td>584.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>584.000000</td>\n",
|
||
" <td>584.000000</td>\n",
|
||
" <td>584.000000</td>\n",
|
||
" <td>0.004181</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-1.386721</td>\n",
|
||
" <td>1.997900</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>53</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.981807</td>\n",
|
||
" <td>12.753652</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001321</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.018194</td>\n",
|
||
" <td>0.025730</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>54</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-3.962446</td>\n",
|
||
" <td>0.002950</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001248</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-6.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.037554</td>\n",
|
||
" <td>0.002950</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>55</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-8.976932</td>\n",
|
||
" <td>18.417400</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001200</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.976932</td>\n",
|
||
" <td>1.381590</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>56</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-8.290108</td>\n",
|
||
" <td>19.388716</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000950</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.290108</td>\n",
|
||
" <td>0.410275</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>57</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.558185</td>\n",
|
||
" <td>0.646650</td>\n",
|
||
" <td>337.500000</td>\n",
|
||
" <td>222.000000</td>\n",
|
||
" <td>453.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>337.500000</td>\n",
|
||
" <td>222.000000</td>\n",
|
||
" <td>453.000000</td>\n",
|
||
" <td>0.008259</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-4.441815</td>\n",
|
||
" <td>0.646650</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>58</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.931802</td>\n",
|
||
" <td>2.792675</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001027</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>-4.931802</td>\n",
|
||
" <td>7.035316</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>59</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>674.500000</td>\n",
|
||
" <td>631.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>631.000000</td>\n",
|
||
" <td>631.000000</td>\n",
|
||
" <td>631.000000</td>\n",
|
||
" <td>0.003288</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-10.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>60</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001974</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>61</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-8.848903</td>\n",
|
||
" <td>18.598459</td>\n",
|
||
" <td>673.500000</td>\n",
|
||
" <td>629.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>629.000000</td>\n",
|
||
" <td>629.000000</td>\n",
|
||
" <td>629.000000</td>\n",
|
||
" <td>0.001706</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.848903</td>\n",
|
||
" <td>1.200530</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>62</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.090808</td>\n",
|
||
" <td>0.014869</td>\n",
|
||
" <td>707.500000</td>\n",
|
||
" <td>697.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>697.000000</td>\n",
|
||
" <td>697.000000</td>\n",
|
||
" <td>697.000000</td>\n",
|
||
" <td>0.000990</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.909192</td>\n",
|
||
" <td>0.014869</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>63</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-11.091834</td>\n",
|
||
" <td>15.426476</td>\n",
|
||
" <td>678.000000</td>\n",
|
||
" <td>638.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>638.000000</td>\n",
|
||
" <td>638.000000</td>\n",
|
||
" <td>638.000000</td>\n",
|
||
" <td>0.002370</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-3.091834</td>\n",
|
||
" <td>4.372514</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>64</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.816241</td>\n",
|
||
" <td>6.788723</td>\n",
|
||
" <td>504.000000</td>\n",
|
||
" <td>398.000000</td>\n",
|
||
" <td>610.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>504.000000</td>\n",
|
||
" <td>398.000000</td>\n",
|
||
" <td>610.000000</td>\n",
|
||
" <td>0.009033</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-0.183759</td>\n",
|
||
" <td>0.282345</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>65</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.971285</td>\n",
|
||
" <td>12.768532</td>\n",
|
||
" <td>639.500000</td>\n",
|
||
" <td>561.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>561.000000</td>\n",
|
||
" <td>561.000000</td>\n",
|
||
" <td>561.000000</td>\n",
|
||
" <td>0.004788</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.028715</td>\n",
|
||
" <td>0.040609</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>66</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-3.978978</td>\n",
|
||
" <td>0.000921</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001102</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-6.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.021022</td>\n",
|
||
" <td>0.000921</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>67</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.548499</td>\n",
|
||
" <td>6.408890</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000945</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-0.451501</td>\n",
|
||
" <td>0.662178</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>68</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-9.647604</td>\n",
|
||
" <td>17.468925</td>\n",
|
||
" <td>570.500000</td>\n",
|
||
" <td>423.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>423.000000</td>\n",
|
||
" <td>423.000000</td>\n",
|
||
" <td>423.000000</td>\n",
|
||
" <td>0.025197</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-1.647604</td>\n",
|
||
" <td>2.330064</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>69</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-10.832811</td>\n",
|
||
" <td>15.792789</td>\n",
|
||
" <td>559.500000</td>\n",
|
||
" <td>401.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>401.000000</td>\n",
|
||
" <td>401.000000</td>\n",
|
||
" <td>401.000000</td>\n",
|
||
" <td>0.038960</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-2.832811</td>\n",
|
||
" <td>4.006200</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>70</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>690.500000</td>\n",
|
||
" <td>663.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>663.000000</td>\n",
|
||
" <td>663.000000</td>\n",
|
||
" <td>663.000000</td>\n",
|
||
" <td>0.004275</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>71</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.983641</td>\n",
|
||
" <td>12.751058</td>\n",
|
||
" <td>465.500000</td>\n",
|
||
" <td>213.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>213.000000</td>\n",
|
||
" <td>213.000000</td>\n",
|
||
" <td>213.000000</td>\n",
|
||
" <td>0.048212</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.016360</td>\n",
|
||
" <td>0.023136</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>72</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.985830</td>\n",
|
||
" <td>12.747961</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001176</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.014170</td>\n",
|
||
" <td>0.020039</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>73</td>\n",
|
||
" <td>0.000100</td>\n",
|
||
" <td>1.293883</td>\n",
|
||
" <td>0.501316</td>\n",
|
||
" <td>506.500000</td>\n",
|
||
" <td>295.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>295.000000</td>\n",
|
||
" <td>295.000000</td>\n",
|
||
" <td>295.000000</td>\n",
|
||
" <td>0.086380</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-4.706117</td>\n",
|
||
" <td>0.501316</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>74</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.637522</td>\n",
|
||
" <td>13.240543</td>\n",
|
||
" <td>587.000000</td>\n",
|
||
" <td>486.000000</td>\n",
|
||
" <td>688.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>587.000000</td>\n",
|
||
" <td>486.000000</td>\n",
|
||
" <td>688.000000</td>\n",
|
||
" <td>0.041948</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-4.637521</td>\n",
|
||
" <td>6.558445</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>75</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-8.195321</td>\n",
|
||
" <td>19.522764</td>\n",
|
||
" <td>644.000000</td>\n",
|
||
" <td>570.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>570.000000</td>\n",
|
||
" <td>570.000000</td>\n",
|
||
" <td>570.000000</td>\n",
|
||
" <td>0.018705</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.195321</td>\n",
|
||
" <td>0.276226</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>76</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-9.506197</td>\n",
|
||
" <td>17.668905</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001101</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-1.506197</td>\n",
|
||
" <td>2.130084</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>77</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-9.085239</td>\n",
|
||
" <td>18.264231</td>\n",
|
||
" <td>641.500000</td>\n",
|
||
" <td>565.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>565.000000</td>\n",
|
||
" <td>565.000000</td>\n",
|
||
" <td>565.000000</td>\n",
|
||
" <td>0.038641</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-1.085240</td>\n",
|
||
" <td>1.534761</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>78</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.289712</td>\n",
|
||
" <td>0.292143</td>\n",
|
||
" <td>683.000000</td>\n",
|
||
" <td>648.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>648.000000</td>\n",
|
||
" <td>648.000000</td>\n",
|
||
" <td>648.000000</td>\n",
|
||
" <td>0.008802</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.710288</td>\n",
|
||
" <td>0.292143</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>79</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.986875</td>\n",
|
||
" <td>12.746484</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001148</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.013125</td>\n",
|
||
" <td>0.018562</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>80</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001387</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>81</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000819</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>82</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001463</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>83</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-13.000000</td>\n",
|
||
" <td>12.727922</td>\n",
|
||
" <td>662.500000</td>\n",
|
||
" <td>607.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>607.000000</td>\n",
|
||
" <td>607.000000</td>\n",
|
||
" <td>607.000000</td>\n",
|
||
" <td>0.027296</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-5.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>84</td>\n",
|
||
" <td>0.000100</td>\n",
|
||
" <td>-8.069077</td>\n",
|
||
" <td>19.701302</td>\n",
|
||
" <td>584.000000</td>\n",
|
||
" <td>450.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>450.000000</td>\n",
|
||
" <td>450.000000</td>\n",
|
||
" <td>450.000000</td>\n",
|
||
" <td>0.104870</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.069076</td>\n",
|
||
" <td>0.097689</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>85</td>\n",
|
||
" <td>0.000200</td>\n",
|
||
" <td>-9.363983</td>\n",
|
||
" <td>17.870026</td>\n",
|
||
" <td>569.000000</td>\n",
|
||
" <td>420.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>420.000000</td>\n",
|
||
" <td>420.000000</td>\n",
|
||
" <td>420.000000</td>\n",
|
||
" <td>0.166438</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-1.363983</td>\n",
|
||
" <td>1.928963</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>86</td>\n",
|
||
" <td>0.000300</td>\n",
|
||
" <td>-13.000000</td>\n",
|
||
" <td>12.727922</td>\n",
|
||
" <td>527.500000</td>\n",
|
||
" <td>337.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>337.000000</td>\n",
|
||
" <td>337.000000</td>\n",
|
||
" <td>337.000000</td>\n",
|
||
" <td>0.278213</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-5.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>87</td>\n",
|
||
" <td>0.000300</td>\n",
|
||
" <td>-0.112757</td>\n",
|
||
" <td>5.169596</td>\n",
|
||
" <td>457.000000</td>\n",
|
||
" <td>196.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>196.000000</td>\n",
|
||
" <td>196.000000</td>\n",
|
||
" <td>196.000000</td>\n",
|
||
" <td>0.325931</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-1.112757</td>\n",
|
||
" <td>1.901471</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>88</td>\n",
|
||
" <td>0.000200</td>\n",
|
||
" <td>-3.634885</td>\n",
|
||
" <td>0.447414</td>\n",
|
||
" <td>587.000000</td>\n",
|
||
" <td>456.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>456.000000</td>\n",
|
||
" <td>456.000000</td>\n",
|
||
" <td>456.000000</td>\n",
|
||
" <td>0.199767</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-4.634885</td>\n",
|
||
" <td>6.623653</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>89</td>\n",
|
||
" <td>0.000400</td>\n",
|
||
" <td>0.871788</td>\n",
|
||
" <td>6.865792</td>\n",
|
||
" <td>508.000000</td>\n",
|
||
" <td>298.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>298.000000</td>\n",
|
||
" <td>298.000000</td>\n",
|
||
" <td>298.000000</td>\n",
|
||
" <td>0.363610</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-0.128212</td>\n",
|
||
" <td>0.205277</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>90</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-4.042986</td>\n",
|
||
" <td>0.094284</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001259</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-6.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-0.042986</td>\n",
|
||
" <td>0.094284</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>91</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-12.983546</td>\n",
|
||
" <td>12.751191</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001957</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>-3.000000</td>\n",
|
||
" <td>4.242640</td>\n",
|
||
" <td>0.016454</td>\n",
|
||
" <td>0.023269</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>92</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-9.239710</td>\n",
|
||
" <td>18.045776</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001780</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-1.239710</td>\n",
|
||
" <td>1.753215</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>93</td>\n",
|
||
" <td>0.000300</td>\n",
|
||
" <td>-0.628619</td>\n",
|
||
" <td>4.722605</td>\n",
|
||
" <td>554.000000</td>\n",
|
||
" <td>390.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>390.000000</td>\n",
|
||
" <td>390.000000</td>\n",
|
||
" <td>390.000000</td>\n",
|
||
" <td>0.312774</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-1.628619</td>\n",
|
||
" <td>2.348463</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>94</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-8.356527</td>\n",
|
||
" <td>19.294785</td>\n",
|
||
" <td>692.500000</td>\n",
|
||
" <td>667.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>667.000000</td>\n",
|
||
" <td>667.000000</td>\n",
|
||
" <td>667.000000</td>\n",
|
||
" <td>0.015856</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.356527</td>\n",
|
||
" <td>0.504206</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>95</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.819553</td>\n",
|
||
" <td>6.786077</td>\n",
|
||
" <td>710.000000</td>\n",
|
||
" <td>702.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>702.000000</td>\n",
|
||
" <td>702.000000</td>\n",
|
||
" <td>702.000000</td>\n",
|
||
" <td>0.002237</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-1.000000</td>\n",
|
||
" <td>7.071068</td>\n",
|
||
" <td>-0.180447</td>\n",
|
||
" <td>0.284991</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>96</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>5.888716</td>\n",
|
||
" <td>0.034997</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001013</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-0.111284</td>\n",
|
||
" <td>0.034997</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>97</td>\n",
|
||
" <td>0.000400</td>\n",
|
||
" <td>1.610486</td>\n",
|
||
" <td>0.819715</td>\n",
|
||
" <td>558.000000</td>\n",
|
||
" <td>398.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>398.000000</td>\n",
|
||
" <td>398.000000</td>\n",
|
||
" <td>398.000000</td>\n",
|
||
" <td>0.391605</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>4.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-4.389514</td>\n",
|
||
" <td>0.819715</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>98</td>\n",
|
||
" <td>0.000300</td>\n",
|
||
" <td>-8.591236</td>\n",
|
||
" <td>18.962856</td>\n",
|
||
" <td>579.000000</td>\n",
|
||
" <td>440.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>440.000000</td>\n",
|
||
" <td>440.000000</td>\n",
|
||
" <td>440.000000</td>\n",
|
||
" <td>0.310268</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-0.591236</td>\n",
|
||
" <td>0.836134</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>99</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-22.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>1.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.001404</td>\n",
|
||
" <td>-2.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>-20.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" <td>0.000000</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <td>100</td>\n",
|
||
" <td>0.000100</td>\n",
|
||
" <td>-11.681906</td>\n",
|
||
" <td>14.591989</td>\n",
|
||
" <td>655.000000</td>\n",
|
||
" <td>592.000000</td>\n",
|
||
" <td>718.000000</td>\n",
|
||
" <td>0.500000</td>\n",
|
||
" <td>592.000000</td>\n",
|
||
" <td>592.000000</td>\n",
|
||
" <td>592.000000</td>\n",
|
||
" <td>0.089281</td>\n",
|
||
" <td>-0.500000</td>\n",
|
||
" <td>2.121320</td>\n",
|
||
" <td>-9.500000</td>\n",
|
||
" <td>14.849242</td>\n",
|
||
" <td>2.000000</td>\n",
|
||
" <td>2.828427</td>\n",
|
||
" <td>-3.681906</td>\n",
|
||
" <td>5.207002</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table><p>"
|
||
],
|
||
"text/plain": [
|
||
"<IPython.core.display.HTML object>"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Unsloth: Will smartly offload gradients to save VRAM!\n",
|
||
"def matmul(A, B):\n",
|
||
" # ensure dimensions\n",
|
||
" m = len(A)\n",
|
||
" n = len(A[0])\n",
|
||
" p = len(B[0]) if B else 0\n",
|
||
" return [[sum(A[i][k] * B[k][j] for k in range(n)) for j in range(p)] for i in range(m)]\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" # A: m x k\n",
|
||
" # B: k x n\n",
|
||
" # returns m x n\n",
|
||
" ...\n",
|
||
"def matmul(A, B):\n",
|
||
" # A: r x p, B: p x c\n",
|
||
" r, p = len(A), len(A[0]) if A else 0\n",
|
||
" p2, c = len(B), len(B[0]) if B else 0\n",
|
||
" if r == 0 or c == 0 or p != p2:\n",
|
||
" raise ValueError(\"Incompatible dimensions for multiplication\")\n",
|
||
" # transpose B to improve locality\n",
|
||
" B_T = list(zip(*B)) # c x p\n",
|
||
" result = [[0] * c for _ in range(r)]\n",
|
||
" for i in range(r):\n",
|
||
" Ai = A[i]\n",
|
||
" Ri = result[i]\n",
|
||
" for j, Bj in enumerate(B_T):\n",
|
||
" s = 0\n",
|
||
" for k in range(p):\n",
|
||
" s += Ai[k] * Bj[k]\n",
|
||
" Ri[j] = s\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list[list[float]]\n",
|
||
" Left‑hand matrix with shape m x k.\n",
|
||
" B : list[list[float]]\n",
|
||
" Right‑hand matrix with shape k x n.\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" list[list[float]]\n",
|
||
" Resulting matrix with shape m x n.\n",
|
||
"\n",
|
||
" Raises\n",
|
||
" ------\n",
|
||
" ValueError\n",
|
||
" If dimensions are incompatible.\n",
|
||
" \"\"\"\n",
|
||
" if not A or not B:\n",
|
||
" return []\n",
|
||
"\n",
|
||
" # Dimensions\n",
|
||
" rows_a, cols_a = len(A), len(A[0])\n",
|
||
" rows_b, cols_b = len(B), len(B[0])\n",
|
||
"\n",
|
||
" if cols_a != rows_b:\n",
|
||
" raise ValueError(\"Incompatible dimensions for multiplication\")\n",
|
||
"\n",
|
||
" # Convert B into columns for faster row‑by‑row multiplication\n",
|
||
" B_t = [list(col) for col in zip(*B)]\n",
|
||
"\n",
|
||
" # Compute each row of the result\n",
|
||
" result = [\n",
|
||
" [sum(a * b for a, b in zip(row_a, col_b)) for col_b in B_t]\n",
|
||
" for row_a in A\n",
|
||
" ]\n",
|
||
"\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Compute the matrix product of A and B using pure Python.\"\"\"\n",
|
||
" # Quick sanity checks\n",
|
||
" m, n = len(A), len(A[0])\n",
|
||
" p, q = len(B), len(B[0])\n",
|
||
" assert n == p, \"Number of columns of A must equal number of rows of B\"\n",
|
||
" # Prepare the result matrix with zeros\n",
|
||
" result = [[0] * q for _ in range(m)]\n",
|
||
" # This variant loops over the outermost index that is likely to be cache-friendly\n",
|
||
" # and prefetches the row of B so that we access its elements in order.\n",
|
||
" for i in range(m):\n",
|
||
" row_a = A[i]\n",
|
||
" for k in range(n):\n",
|
||
" aik = row_a[k]\n",
|
||
" if aik: # skip the zero case to save work\n",
|
||
" row_b = B[k]\n",
|
||
" for j in range(q):\n",
|
||
" result[i][j] += aik * row_b[j]\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" m = len(A)\n",
|
||
" if m==0: return []\n",
|
||
" n = len(A[0]) or 0\n",
|
||
" p = len(B[0]) if B else 0\n",
|
||
" # ensure B has n rows\n",
|
||
" # Use list comprehension summing product over k\n",
|
||
" # Compute B transposed for column-wise access: BT = list(zip(*B))\n",
|
||
" BT = list(zip(*B))\n",
|
||
" return [[sum(a*b for a,b in zip(row,col)) for col in BT] for row in A]\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices where each matrix is represented as a list of lists\n",
|
||
" and the elements are integers or floats.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list[list[int|float]]\n",
|
||
" Left‑hand matrix of size (m × p).\n",
|
||
" B : list[list[int|float]]\n",
|
||
" Right‑hand matrix of size (p × n).\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" list[list[int|float]]\n",
|
||
" The product matrix C = A @ B of size (m × n).\n",
|
||
" \"\"\"\n",
|
||
"\n",
|
||
" # Dimensions: A: m×p, B: p×n\n",
|
||
" m, p = len(A), len(A[0])\n",
|
||
" p2, n = len(B), len(B[0])\n",
|
||
" if p != p2:\n",
|
||
" raise ValueError(\"Inner dimensions must agree for matrix multiplication\")\n",
|
||
"\n",
|
||
" # Pre‑transpose B so that column access is contiguous\n",
|
||
" # This reduces random memory access during the dot product\n",
|
||
" B_T = [list(col) for col in zip(*B)]\n",
|
||
"\n",
|
||
" result = []\n",
|
||
" for i, row in enumerate(A):\n",
|
||
" # Compute each entry of the i‑th row of the result\n",
|
||
" result_row = []\n",
|
||
" for j, col in enumerate(B_T):\n",
|
||
" # use a local variable for speed\n",
|
||
" dot = 0\n",
|
||
" for a, b in zip(row, col):\n",
|
||
" dot += a * b\n",
|
||
" result_row.append(dot)\n",
|
||
" result.append(result_row)\n",
|
||
"\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B using plain Python.\n",
|
||
" A: list of lists (m × n), B: list of lists (n × p).\n",
|
||
" Returns the product (m × p) as a new list of lists.\n",
|
||
" \"\"\"\n",
|
||
" if not A or not B:\n",
|
||
" return []\n",
|
||
"\n",
|
||
" m = len(A)\n",
|
||
" n = len(A[0])\n",
|
||
" p = len(B[0])\n",
|
||
"\n",
|
||
" # Quick compatibility check\n",
|
||
" assert len(B) == n, \"Incompatible matrix dimensions\"\n",
|
||
"\n",
|
||
" # Allocate result matrix\n",
|
||
" result = [[0] * p for _ in range(m)]\n",
|
||
"\n",
|
||
" # Standard triple‑loop multiplication, with a small speed‑up:\n",
|
||
" # pull outer indices, cache row and column values locally,\n",
|
||
" # and skip inner loop when the coefficient is zero.\n",
|
||
" for i in range(m):\n",
|
||
" Ai = A[i]\n",
|
||
" Ri = result[i]\n",
|
||
" for k in range(n):\n",
|
||
" aik = Ai[k]\n",
|
||
" if aik: # skip zero entries\n",
|
||
" Bk = B[k]\n",
|
||
" for j in range(p):\n",
|
||
" Ri[j] += aik * Bk[j]\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" # number of rows in A\n",
|
||
" m = len(A)\n",
|
||
" # number of columns in B\n",
|
||
" p = len(B[0]) if B else 0\n",
|
||
" # number of columns in A (used as number of rows in B)\n",
|
||
" k = len(A[0]) if A else 0\n",
|
||
"\n",
|
||
" # If shapes are incompatible, raise an error\n",
|
||
" if len(B) != k:\n",
|
||
" raise ValueError(\"Incompatible matrices: A.shape[1] != B.shape[0]\")\n",
|
||
"\n",
|
||
" # Result matrix initialised with zeros\n",
|
||
" result = [[0] * p for _ in range(m)]\n",
|
||
"\n",
|
||
" # Triple‑loop multiplication\n",
|
||
" for i in range(m):\n",
|
||
" for j in range(p):\n",
|
||
" # Compute the dot product of row i of A and column j of B\n",
|
||
" s = 0\n",
|
||
" for t in range(k):\n",
|
||
" s += A[i][t] * B[t][j]\n",
|
||
" result[i][j] = s\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" # Determine dimensions\n",
|
||
" m, n = len(A), len(A[0])\n",
|
||
" nB, p = len(B), len(B[0])\n",
|
||
" assert n == nB, \"Incompatible matrices\"\n",
|
||
" result = [[0]*p for _ in range(m)]\n",
|
||
" # Multiply\n",
|
||
" for i in range(m):\n",
|
||
" Ai = A[i]\n",
|
||
" for k in range(n):\n",
|
||
" aik = Ai[k]\n",
|
||
" if aik:\n",
|
||
" Bk = B[k]\n",
|
||
" for j in range(p):\n",
|
||
" result[i][j] += aik * Bk[j]\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Fast matrix product using only native Python.\n",
|
||
"\n",
|
||
" Args:\n",
|
||
" A (List[List[Number]]): left matrix (n × m)\n",
|
||
" B (List[List[Number]]): right matrix (m × p)\n",
|
||
"\n",
|
||
" Returns:\n",
|
||
" List[List[Number]]: the product A * B (n × p)\n",
|
||
"\n",
|
||
" Raises:\n",
|
||
" ValueError: if the matrices cannot be multiplied\n",
|
||
" \"\"\"\n",
|
||
" # Basic shape checks\n",
|
||
" if not A or not A[0] or not B or not B[0]:\n",
|
||
" raise ValueError(\"Input matrices must be non‑empty\")\n",
|
||
" n, m = len(A), len(A[0])\n",
|
||
" if m != len(B):\n",
|
||
" raise ValueError(\"Number of columns of A must equal number of rows of B\")\n",
|
||
"\n",
|
||
" # Transpose B once for better locality\n",
|
||
" B_T = list(zip(*B)) # now each element of B_T is a tuple representing a column\n",
|
||
"\n",
|
||
" # Compute the product\n",
|
||
" result = []\n",
|
||
" for row in A:\n",
|
||
" # dot(row, col) for each column\n",
|
||
" result.append([sum(a * b for a, b in zip(row, col)) for col in B_T])\n",
|
||
"\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" ...\n",
|
||
"def matmul(A, B):\n",
|
||
" n = len(A)\n",
|
||
" m = len(B[0])\n",
|
||
" k = len(B)\n",
|
||
" result = [[0]*m for _ in range(n)]\n",
|
||
" for i in range(n):\n",
|
||
" for j in range(m):\n",
|
||
" s = 0\n",
|
||
" for l in range(k):\n",
|
||
" s += A[i][l] * B[l][j]\n",
|
||
" result[i][j] = s\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" m = len(A)\n",
|
||
" n = len(B[0])\n",
|
||
" p = len(B)\n",
|
||
" return [[sum(A[i][k] * B[k][j] for k in range(p)) for j in range(n)] for i in range(m)]\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" import math\n",
|
||
" # Assume square matrices of same size and power of 2\n",
|
||
" n = len(A)\n",
|
||
" if n == 0:\n",
|
||
" return []\n",
|
||
" def add(X, Y):\n",
|
||
" return [[X[i][j] + Y[i][j] for j in range(n)] for i in range(n)]\n",
|
||
" def sub(X, Y):\n",
|
||
" return [[X[i][j] - Y[i][j] for j in range(n)] for i in range(n)]\n",
|
||
" def split(M):\n",
|
||
" k = n // 2\n",
|
||
" return [ [row[:k] for row in M[:k]],\n",
|
||
" [row[:k] for row in M[k:]],\n",
|
||
" [row[k:] for row in M[:k]],\n",
|
||
" [row[k:] for row in M[k:]] ]\n",
|
||
" def combine(A11, A12, A21, A22):\n",
|
||
" k = len(A11)\n",
|
||
" result = [ [0]* (k*2) for _ in range(k*2) ]\n",
|
||
" for i in range(k):\n",
|
||
" result[i][:k] = A11[i]\n",
|
||
" result[i][k:] = A12[i]\n",
|
||
" result[i+k][:k] = A21[i]\n",
|
||
" result[i+k][k:] = A22[i]\n",
|
||
" return result\n",
|
||
" def strassen(X, Y):\n",
|
||
" if n == 1:\n",
|
||
" return [[X[0][0]*Y[0][0]]]\n",
|
||
" a, b, c, d = split(X)\n",
|
||
" e, f, g, h = split(Y)\n",
|
||
" p1 = strassen(a, sub(f, h))\n",
|
||
" p2 = strassen(add(a, b), h)\n",
|
||
" p3 = strassen(add(c, d), e)\n",
|
||
" p4 = strassen(d, sub(g, e))\n",
|
||
" p5 = strassen(add(a, d), add(e, h))\n",
|
||
" p6 = strassen(sub(b, d), add(g, h))\n",
|
||
" p7 = strassen(sub(a, c), add(e, f))\n",
|
||
" c11 = add(sub(add(p5, p4), p2), p6)\n",
|
||
" c12 = add(p1, p2)\n",
|
||
" c21 = add(p3, p4)\n",
|
||
" c22 = sub(sub(add(p1, p5), p3), p7)\n",
|
||
" return combine(c11, c12, c21, c22)\n",
|
||
" return strassen(A, B)\n",
|
||
"def matmul(A, B):\n",
|
||
" n = len(A)\n",
|
||
" m = len(A[0])\n",
|
||
" p = len(B[0])\n",
|
||
" assert len(B) == m\n",
|
||
" BT = list(zip(*B)) # transposed as tuples\n",
|
||
" C = [[sum(Ai[k] * BTj[k] for k in range(m)) for BTj in BT] for Ai in A]\n",
|
||
" return C\n",
|
||
"def matmul(A, B):\n",
|
||
" n = len(A)\n",
|
||
" m = len(B[0])\n",
|
||
" p = len(B)\n",
|
||
" # transpose B\n",
|
||
" B_T = list(map(list, zip(*B))) # list of columns\n",
|
||
" return [[sum(a*b for a,b in zip(row, col)) for col in B_T] for row in A]\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" ...\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Matrix multiplication using only native Python (no external libraries).\n",
|
||
"\n",
|
||
" Works for arbitrary sized matrices with compatible dimensions.\n",
|
||
" The algorithm transposes matrix B to enhance cache locality,\n",
|
||
" then uses a list‑comprehension to calculate the dot–product of\n",
|
||
" corresponding rows and columns.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list[list[Number]]\n",
|
||
" Left matrix of shape (m, n).\n",
|
||
" B : list[list[Number]]\n",
|
||
" Right matrix of shape (n, p).\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" list[list[Number]]\n",
|
||
" Resulting product matrix of shape (m, p).\n",
|
||
" \"\"\"\n",
|
||
" # Transpose B for efficient column access\n",
|
||
" B_transposed = list(zip(*B)) # tuples, one per column of B\n",
|
||
" return [\n",
|
||
" [\n",
|
||
" # dot product of row from A and column from B\n",
|
||
" sum(a * b for a, b in zip(row_a, col_b))\n",
|
||
" for col_b in B_transposed\n",
|
||
" ]\n",
|
||
" for row_a in A\n",
|
||
" ]\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" # check dimension matches\n",
|
||
" nrows_a = len(A)\n",
|
||
" ncols_a = len(A[0]) if A else 0\n",
|
||
" nrows_b = len(B)\n",
|
||
" ncols_b = len(B[0]) if B else 0\n",
|
||
" if ncols_a != nrows_b:\n",
|
||
" raise ValueError(\"Incompatible dimensions\")\n",
|
||
" # transpose B for cache locality\n",
|
||
" BT = list(zip(*B)) # tuple of tuples used as rows\n",
|
||
" result = [[0]*ncols_b for _ in range(nrows_a)]\n",
|
||
" for i in range(nrows_a):\n",
|
||
" ai = A[i]\n",
|
||
" ri = result[i]\n",
|
||
" for j in range(ncols_b):\n",
|
||
" s = 0\n",
|
||
" bj = BT[j]\n",
|
||
" for k in range(ncols_a):\n",
|
||
" s += ai[k] * bj[k]\n",
|
||
" ri[j] = s\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" B_T = list(zip(*B))\n",
|
||
" res = [[sum(a*b for a,b in zip(row, col)) for col in B_T] for row in A]\n",
|
||
" return res\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two square matrices A and B.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list[list[float]]\n",
|
||
" First n × n matrix.\n",
|
||
" B : list[list[float]]\n",
|
||
" Second n × n matrix.\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" list[list[float]]\n",
|
||
" The product matrix C = A @ B.\n",
|
||
" \"\"\"\n",
|
||
" # Transpose B once for O(1) column access\n",
|
||
" B_T = list(zip(*B))\n",
|
||
"\n",
|
||
" # Compute C[i][j] = dot(A[i], B_T[j])\n",
|
||
" return [[sum(a * b for a, b in zip(row, col))\n",
|
||
" for col in B_T]\n",
|
||
" for row in A]\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B using native Python lists.\n",
|
||
" `A` and `B` must be rectangular (i.e. all rows the same length).\n",
|
||
"\n",
|
||
" Returns a new matrix containing the product.\n",
|
||
" Raises ValueError if the inner dimensions do not match.\n",
|
||
" \"\"\"\n",
|
||
" if not A or not B:\n",
|
||
" return []\n",
|
||
"\n",
|
||
" n_rows_A, n_cols_A = len(A), len(A[0])\n",
|
||
" n_rows_B, n_cols_B = len(B), len(B[0])\n",
|
||
"\n",
|
||
" if n_cols_A != n_rows_B:\n",
|
||
" raise ValueError(\"cannot multiply: inner dimensions do not match\")\n",
|
||
"\n",
|
||
" # preallocate result matrix\n",
|
||
" result = [[0] * n_cols_B for _ in range(n_rows_A)]\n",
|
||
"\n",
|
||
" for i in range(n_rows_A):\n",
|
||
" # Local references for speed\n",
|
||
" row_a = A[i]\n",
|
||
" for k in range(n_cols_A):\n",
|
||
" aik = row_a[k]\n",
|
||
" if aik == 0:\n",
|
||
" continue # skip zero multiplications\n",
|
||
" row_b = B[k]\n",
|
||
" for j in range(n_cols_B):\n",
|
||
" result[i][j] += aik * row_b[j]\n",
|
||
"\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"None\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"None\n",
|
||
"None\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Return the matrix product of A and B.\n",
|
||
"\n",
|
||
" A must be an `n×m` matrix, B an `m×p` matrix.\n",
|
||
" Matrices are represented as nested lists of numbers.\n",
|
||
" \"\"\"\n",
|
||
" if not A or not B:\n",
|
||
" return []\n",
|
||
"\n",
|
||
" # Transpose B once so we can iterate over rows efficiently\n",
|
||
" B_T = list(zip(*B))\n",
|
||
"\n",
|
||
" # Compute each entry using a dot‑product of corresponding rows\n",
|
||
" return [\n",
|
||
" [sum(a * b for a, b in zip(row_a, col_b)) for col_b in B_T]\n",
|
||
" for row_a in A\n",
|
||
" ]\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" # A is m x p, B is p x n\n",
|
||
" m = len(A)\n",
|
||
" p = len(A[0]) # find p\n",
|
||
" n = len(B[0])\n",
|
||
" # create result m x n\n",
|
||
" result = [... for i in ...]\n",
|
||
"def matmul(A, B):\n",
|
||
" m, p = len(A), len(A[0]) if A else 0\n",
|
||
" p2, n = len(B), len(B[0]) if B else 0\n",
|
||
" if p != p2: raise ValueError(\"Incompatible dimensions\")\n",
|
||
" # Precompute transpose of B for cache-friendly access\n",
|
||
" Bt = list(zip(*B))\n",
|
||
" return [[sum(a * b for a, b in zip(row, col)) for col in Bt] for row in A]\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"None\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A (m×n) and B (n×p) given as lists of lists.\n",
|
||
" Uses only native Python code and is tuned for speed by transposing B.\n",
|
||
" \"\"\"\n",
|
||
" if not A:\n",
|
||
" return []\n",
|
||
"\n",
|
||
" n_rows_A, n_cols_A = len(A), len(A[0])\n",
|
||
" # Basic consistency check – assume all rows have equal length\n",
|
||
" # and B has compatible dimensions.\n",
|
||
" n_rows_B, n_cols_B = len(B), len(B[0]) if B else 0\n",
|
||
"\n",
|
||
" # Transpose B to access its columns as tuples (faster indexing)\n",
|
||
" B_T = list(zip(*B)) # shape: (p × n)\n",
|
||
"\n",
|
||
" result = []\n",
|
||
" for row_A in A: # iterate over rows of A\n",
|
||
" # Compute the dot product of row_A with each column of B\n",
|
||
" res_row = [sum(a * b for a, b in zip(row_A, col_B)) for col_B in B_T]\n",
|
||
" result.append(res_row)\n",
|
||
"\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B (lists of lists) using native Python.\n",
|
||
" The matrices are assumed to be square and of compatible dimensions.\n",
|
||
" \"\"\"\n",
|
||
" n = len(A)\n",
|
||
" # Transpose B to improve cache locality for the inner sum\n",
|
||
" B_T = list(zip(*B)) # each element is a tuple\n",
|
||
" return [[sum(a * b for a, b in zip(row, col))\n",
|
||
" for col in B_T]\n",
|
||
" for row in A]\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B using only native Python code.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list of lists (m x k)\n",
|
||
" B : list of lists (k x n)\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" C : list of lists (m x n)\n",
|
||
" Product matrix such that C[i][j] = sum(A[i][p] * B[p][j] for p in range(k))\n",
|
||
"\n",
|
||
" Raises\n",
|
||
" ------\n",
|
||
" ValueError\n",
|
||
" If the number of columns in A does not equal the number of rows in B.\n",
|
||
" \"\"\"\n",
|
||
" if not A or not B:\n",
|
||
" raise ValueError(\"Both matrices must be non‑empty.\")\n",
|
||
" m, k1 = len(A), len(A[0])\n",
|
||
" k2, n = len(B), len(B[0])\n",
|
||
" if k1 != k2:\n",
|
||
" raise ValueError(f\"Incompatible shapes: {m}x{k1} multiplied by {k2}x{n}\")\n",
|
||
" # Pre‑compute columns of B for faster access\n",
|
||
" B_cols = list(zip(*B)) # n tuples each of length k\n",
|
||
" # Compute the product\n",
|
||
" return [[sum(a * b for a, b in zip(row, col))\n",
|
||
" for col in B_cols] for row in A]\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Fast matrix multiplication for plain Python objects.\n",
|
||
" A : list of m rows, each a list of n numbers\n",
|
||
" B : list of n rows, each a list of p numbers\n",
|
||
" Returns a new matrix of shape m × p.\n",
|
||
" \"\"\"\n",
|
||
" m = len(A)\n",
|
||
" if m == 0:\n",
|
||
" return []\n",
|
||
" n = len(A[0])\n",
|
||
" # Verify dimension compatibility\n",
|
||
" if len(B) != n or any(len(row) != n for row in A):\n",
|
||
" raise ValueError(\"Inner dimensions must agree.\")\n",
|
||
" p = len(B[0])\n",
|
||
"\n",
|
||
" # Allocate result matrix\n",
|
||
" result = [[0] * p for _ in range(m)]\n",
|
||
"\n",
|
||
" # Standard triple-loop, optimized for speed in pure Python\n",
|
||
" for i in range(m):\n",
|
||
" row_a = A[i]\n",
|
||
" row_res = result[i]\n",
|
||
" for k in range(n):\n",
|
||
" a_val = row_a[k]\n",
|
||
" row_b = B[k]\n",
|
||
" # Use local variables for performance\n",
|
||
" for j in range(p):\n",
|
||
" row_res[j] += a_val * row_b[j]\n",
|
||
"\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Multiply two matrices A and B.\n",
|
||
"\n",
|
||
" A: list of m rows, each containing n elements.\n",
|
||
" B: list of n rows, each containing p elements.\n",
|
||
" Returns a new list of list representing the product matrix of shape (m, p).\n",
|
||
" \"\"\"\n",
|
||
" # Basic sanity checks\n",
|
||
" if not A or not B:\n",
|
||
" raise ValueError(\"Input matrices must be non‑empty.\")\n",
|
||
" m, n = len(A), len(A[0])\n",
|
||
" nB, p = len(B), len(B[0])\n",
|
||
" if n != nB:\n",
|
||
" raise ValueError(\"Number of columns of A must equal number of rows of B.\")\n",
|
||
" for row in A:\n",
|
||
" if len(row) != n:\n",
|
||
" raise ValueError(\"All rows of A must have the same length.\")\n",
|
||
" for row in B:\n",
|
||
" if len(row) != p:\n",
|
||
" raise ValueError(\"All rows of B must have the same length.\")\n",
|
||
"\n",
|
||
" # Allocate the result matrix (m x p) initialized to 0\n",
|
||
" result = [[0] * p for _ in range(m)]\n",
|
||
"\n",
|
||
" # Perform multiplication\n",
|
||
" for i in range(m):\n",
|
||
" rowA = A[i]\n",
|
||
" rowR = result[i]\n",
|
||
" for k in range(n):\n",
|
||
" aik = rowA[k]\n",
|
||
" if aik: # Skip work for zero multiplication\n",
|
||
" rowB = B[k]\n",
|
||
" for j in range(p):\n",
|
||
" rowR[j] += aik * rowB[j]\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" # Validate dimensions\n",
|
||
" if not A or not B:\n",
|
||
" return []\n",
|
||
" if len(A[0]) != len(B):\n",
|
||
" raise ValueError(\"Matrix dimensions do not match for multiplication.\")\n",
|
||
" B_cols = list(zip(*B)) # transpose B\n",
|
||
" result = [[sum(a*b for a,b in zip(row, col)) for col in B_cols] for row in A]\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Multiply matrices A × B (list‑of‑list format) using an optimized pure‑Python routine.\"\"\"\n",
|
||
" n, p = len(A), len(A[0]) # rows of A, columns of B (must match)\n",
|
||
" m = len(B[0]) # columns of B\n",
|
||
" # Result matrix initialized with zeros\n",
|
||
" result = [[0] * m for _ in range(n)]\n",
|
||
" for i in range(n):\n",
|
||
" rowA = A[i]\n",
|
||
" rowR = result[i]\n",
|
||
" for k in range(p):\n",
|
||
" aik = rowA[k]\n",
|
||
" if aik: # skip zero entries for a small extra speedup\n",
|
||
" rowBk = B[k]\n",
|
||
" for j in range(m):\n",
|
||
" rowR[j] += aik * rowBk[j]\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Fast matrix multiplication using only native Python code.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list[list[float]]\n",
|
||
" Left hand matrix of shape (n, m).\n",
|
||
" B : list[list[float]]\n",
|
||
" Right hand matrix of shape (m, q).\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" list[list[float]]\n",
|
||
" The product matrix of shape (n, q).\n",
|
||
"\n",
|
||
" Notes\n",
|
||
" -----\n",
|
||
" The routine pre-allocates the result matrix and uses local variable\n",
|
||
" bindings to reduce attribute look‑ups inside the innermost loop,\n",
|
||
" which gives a noticeable speed boost for large matrices.\n",
|
||
" \"\"\"\n",
|
||
" # Basic dimensions checking\n",
|
||
" n, m = len(A), len(A[0])\n",
|
||
" m2, q = len(B), len(B[0])\n",
|
||
" if m != m2:\n",
|
||
" raise ValueError(\"Number of columns in A must equal number of rows in B.\")\n",
|
||
"\n",
|
||
" # Pre‑allocate result matrix with zeros\n",
|
||
" result = [[0.0] * q for _ in range(n)]\n",
|
||
"\n",
|
||
" # Perform multiplication\n",
|
||
" for i in range(n):\n",
|
||
" rowA = A[i]\n",
|
||
" rowR = result[i]\n",
|
||
" for k in range(m):\n",
|
||
" aik = rowA[k]\n",
|
||
" rowB = B[k]\n",
|
||
" for j in range(q):\n",
|
||
" rowR[j] += aik * rowB[j]\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" B_T = list(zip(*B)) # transpose B for inner product\n",
|
||
" return [[sum(a*b for a,b in zip(row, col)) for col in B_T] for row in A]\n",
|
||
"def matmul(A, B):\n",
|
||
" # A: m x n, B: n x p\n",
|
||
" m, n = len(A), len(A[0])\n",
|
||
" n2, p = len(B), len(B[0])\n",
|
||
" assert n==n2\n",
|
||
" # initialize result matrix\n",
|
||
" C = [[0]*p for _ in range(m)]\n",
|
||
" # transpose B for better locality\n",
|
||
" B_T = list(zip(*B))\n",
|
||
" for i in range(m):\n",
|
||
" Ai = A[i]\n",
|
||
" Ci = C[i]\n",
|
||
" for k in range(n):\n",
|
||
" aik = Ai[k]\n",
|
||
" Bk = B_T[k]\n",
|
||
" for j in range(p):\n",
|
||
" Ci[j] += aik * Bk[j]\n",
|
||
" return C\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Fast matrix multiplication using pure Python.\n",
|
||
"\n",
|
||
" Arguments:\n",
|
||
" A: List of lists, the left matrix of size m x n.\n",
|
||
" B: List of lists, the right matrix of size n x p.\n",
|
||
"\n",
|
||
" Returns a new matrix C of size m x p where C[i][j] = sum(A[i][k] * B[k][j] for k in range(n)).\n",
|
||
"\n",
|
||
" This implementation transposes B once to enable efficient column access\n",
|
||
" and uses nested list comprehensions together with the built‑in `sum`\n",
|
||
" function, which is implemented in C.\n",
|
||
" \"\"\"\n",
|
||
" # Verify dimensions\n",
|
||
" if not A or not B:\n",
|
||
" raise ValueError(\"Matrices cannot be empty\")\n",
|
||
" n = len(A[0])\n",
|
||
" if any(len(row) != n for row in A):\n",
|
||
" raise ValueError(\"All rows in A must have the same length\")\n",
|
||
" if len(B) != n:\n",
|
||
" raise ValueError(\"Number of columns in A must equal number of rows in B\")\n",
|
||
" p = len(B[0])\n",
|
||
" if any(len(row) != p for row in B):\n",
|
||
" raise ValueError(\"All rows in B must have the same length\")\n",
|
||
"\n",
|
||
" # Transpose B to get columns as rows\n",
|
||
" B_cols = list(zip(*B))\n",
|
||
"\n",
|
||
" # Compute product\n",
|
||
" return [[sum(a * b for a, b in zip(row, col)) for col in B_cols] for row in A]\n",
|
||
"def matmul(A, B):\n",
|
||
" BT = list(zip(*B))\n",
|
||
" return [[sum(a*b for a,b in zip(row, col)) for col in BT] for row in A]\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Multiplies matrix A by matrix B using pure native Python.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list[list[float]]\n",
|
||
" The first matrix of shape (l, m).\n",
|
||
" B : list[list[float]]\n",
|
||
" The second matrix of shape (m, n).\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" list[list[float]]\n",
|
||
" The product matrix of shape (l, n).\n",
|
||
" \"\"\"\n",
|
||
" # Pre‑get dimensions for speed\n",
|
||
" l = len(A) # Number of rows in A\n",
|
||
" m = len(A[0]) # Number of columns in A / rows in B\n",
|
||
" n = len(B[0]) # Number of columns in B\n",
|
||
"\n",
|
||
" # The result will have shape (l, n)\n",
|
||
" result = [[0.0] * n for _ in range(l)]\n",
|
||
"\n",
|
||
" for i in range(l):\n",
|
||
" Ai = A[i]\n",
|
||
" for k in range(m):\n",
|
||
" aik = Ai[k]\n",
|
||
" Bk = B[k]\n",
|
||
" # Unroll column loop to reduce attribute lookups\n",
|
||
" for j in range(n):\n",
|
||
" result[i][j] += aik * Bk[j]\n",
|
||
"\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A (n x m) and B (m x p) using only native Python.\n",
|
||
" Returns the resulting matrix as a list of lists.\n",
|
||
" \"\"\"\n",
|
||
" n = len(A)\n",
|
||
" m = len(A[0])\n",
|
||
" if len(B) != m:\n",
|
||
" raise ValueError(\"Number of columns in A must equal number of rows in B\")\n",
|
||
" p = len(B[0])\n",
|
||
"\n",
|
||
" # Pre‑allocate result matrix with zeros\n",
|
||
" result = [[0] * p for _ in range(n)]\n",
|
||
"\n",
|
||
" for i in range(n):\n",
|
||
" row_a = A[i]\n",
|
||
" for k in range(m):\n",
|
||
" aik = row_a[k] # A[i][k]\n",
|
||
" row_b = B[k] # The k-th row of B\n",
|
||
" for j in range(p):\n",
|
||
" result[i][j] += aik * row_b[j] # C[i][j] += A[i][k] * B[k][j]\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" # assume A dims m x n, B n x p\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" # Should handle maybe rectangular matrices\n",
|
||
" ...\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" result = []\n",
|
||
" for i in range(len(A)):\n",
|
||
" res_row = []\n",
|
||
" for j in range(len(B[0])):\n",
|
||
" sum_val = 0\n",
|
||
" for k in range(len(B)):\n",
|
||
" sum_val += A[i][k] * B[k][j]\n",
|
||
" res_row.append(sum_val)\n",
|
||
" result.append(res_row)\n",
|
||
" return result\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices represented as lists of lists using only\n",
|
||
" standard Python code. Raises a ValueError if the matrices cannot\n",
|
||
" be multiplied.\n",
|
||
" \n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : List[List[Number]]\n",
|
||
" The left-hand-side matrix of shape (m, n).\n",
|
||
" B : List[List[Number]]\n",
|
||
" The right-hand-side matrix of shape (n, p).\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" C : List[List[Number]]\n",
|
||
" The product matrix of shape (m, p).\n",
|
||
" \"\"\"\n",
|
||
" if not A or not B:\n",
|
||
" raise ValueError(\"Empty matrices cannot be multiplied\")\n",
|
||
"\n",
|
||
" # Verify inner dimensions match\n",
|
||
" n = len(A[0])\n",
|
||
" for row in A:\n",
|
||
" if len(row) != n:\n",
|
||
" raise ValueError(\"All rows of A must have the same length\")\n",
|
||
" if len(B) != n:\n",
|
||
" raise ValueError(\"Number of columns in A must equal number of rows in B\")\n",
|
||
"\n",
|
||
" p = len(B[0])\n",
|
||
" for row in B:\n",
|
||
" if len(row) != p:\n",
|
||
" raise ValueError(\"All rows of B must have the same length\")\n",
|
||
"\n",
|
||
" # Transpose B so that columns can be accessed as tuples\n",
|
||
" B_T = list(zip(*B)) # Each element is a tuple of length n\n",
|
||
"\n",
|
||
" # Compute the product\n",
|
||
" C = []\n",
|
||
" for a_row in A:\n",
|
||
" c_row = []\n",
|
||
" for b_col in B_T:\n",
|
||
" dot_product = sum(x * y for x, y in zip(a_row, b_col))\n",
|
||
" c_row.append(dot_product)\n",
|
||
" C.append(c_row)\n",
|
||
"\n",
|
||
" return C\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B represented as nested lists.\n",
|
||
" \n",
|
||
" Parameters:\n",
|
||
" A (list[list[float]]): Matrix of size (m x n).\n",
|
||
" B (list[list[float]]): Matrix of size (n x p).\n",
|
||
" \n",
|
||
" Returns:\n",
|
||
" list[list[float]]: Resultant matrix of size (m x p).\n",
|
||
" \"\"\"\n",
|
||
" # Pre‑compute the columns of B\n",
|
||
" B_cols = list(zip(*B))\n",
|
||
" \n",
|
||
" # Compute the product row by row\n",
|
||
" return [\n",
|
||
" [\n",
|
||
" sum(a * b for a, b in zip(row, col))\n",
|
||
" for col in B_cols\n",
|
||
" ]\n",
|
||
" for row in A\n",
|
||
" ]\n",
|
||
"def matmul(A, B):\n",
|
||
" # Basic dimension check\n",
|
||
" if not A or not B:\n",
|
||
" return []\n",
|
||
" n_rows_a = len(A)\n",
|
||
" n_cols_a = len(A[0])\n",
|
||
" n_rows_b = len(B)\n",
|
||
" n_cols_b = len(B[0])\n",
|
||
" if n_cols_a != n_rows_b:\n",
|
||
" raise ValueError(\"Incompatible dimensions for matrix multiplication\")\n",
|
||
" result = [[0] * n_cols_b for _ in range(n_rows_a)]\n",
|
||
" for i in range(n_rows_a):\n",
|
||
" for k in range(n_cols_a):\n",
|
||
" aik = A[i][k]\n",
|
||
" if aik == 0:\n",
|
||
" continue\n",
|
||
" for j in range(n_cols_b):\n",
|
||
" result[i][j] += aik * B[k][j]\n",
|
||
" return result\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" # A: m x n, B: n x p\n",
|
||
" # returns m x p\n",
|
||
" # check sizes\n",
|
||
" m, n = len(A), len(A[0])\n",
|
||
" assert len(B) == n\n",
|
||
" p = len(B[0])\n",
|
||
" # Precompute transpose of B\n",
|
||
" Bt = list(zip(*B))\n",
|
||
" res = [[sum(a*b for a,b in zip(row, col)) for col in Bt] for row in A]\n",
|
||
" return res\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Multiply two matrices A and B (list of lists) purely in plain Python.\"\"\"\n",
|
||
" m, n = len(A), len(A[0])\n",
|
||
" nB, p = len(B), len(B[0])\n",
|
||
" if n != nB:\n",
|
||
" raise ValueError(\"Inner matrix dimensions must agree.\")\n",
|
||
" # Pre‑allocate result matrix\n",
|
||
" C = [[0] * p for _ in range(m)]\n",
|
||
" # Perform multiplication in the ctr order: i, k, j\n",
|
||
" for i in range(m):\n",
|
||
" rowA = A[i]\n",
|
||
" rowC = C[i]\n",
|
||
" for k in range(n):\n",
|
||
" aik = rowA[k]\n",
|
||
" if aik: # skip zero multiplications\n",
|
||
" rowB = B[k]\n",
|
||
" for j in range(p):\n",
|
||
" rowC[j] += aik * rowB[j]\n",
|
||
" return C\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" B_T = list(zip(*B))\n",
|
||
" return [[sum(a*b for a,b in zip(row, col)) for col in B_T] for row in A]\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" ...\n",
|
||
"def matmul(A, B):\n",
|
||
" ...\n",
|
||
"def matmul(A, B):\n",
|
||
" ...\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" # assume A rows, B columns\n",
|
||
" m, k1 = len(A), len(A[0]) if A else 0\n",
|
||
" k2, n = len(B), len(B[0]) if B else 0\n",
|
||
" assert k1 == k2, \"Inner dimensions must match\"\n",
|
||
" B_T = list(zip(*B)) # transposed B\n",
|
||
" result = [[sum(a*b for a,b in zip(row, col)) for col in B_T] for row in A]\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B (both given as lists of lists) using\n",
|
||
" only native Python constructs.\n",
|
||
"\n",
|
||
" The function first validates that the inner dimensions match (number of\n",
|
||
" columns in A must equal the number of rows in B). Then it computes the\n",
|
||
" product using a straightforward triple‑loop but expressed in a compact\n",
|
||
" list‑comprehension. The columns of B are accessed by transposing B\n",
|
||
" once via ``zip(*B)``, which avoids explicit indexing and gives good\n",
|
||
" cache locality in Python.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : List[List[Number]]\n",
|
||
" Left‑hand matrix of size m × n.\n",
|
||
"\n",
|
||
" B : List[List[Number]]\n",
|
||
" Right‑hand matrix of size n × p.\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" List[List[Number]]\n",
|
||
" The matrix product of A and B, which has shape m × p.\n",
|
||
"\n",
|
||
" Raises\n",
|
||
" ------\n",
|
||
" ValueError\n",
|
||
" If the matrices cannot be multiplied due to incompatible dimensions.\n",
|
||
" \"\"\"\n",
|
||
" # Validate dimensions\n",
|
||
" if not A or not B:\n",
|
||
" raise ValueError(\"Matrices cannot be empty\")\n",
|
||
" n_cols_A = len(A[0])\n",
|
||
" n_rows_B = len(B)\n",
|
||
" if n_cols_A != n_rows_B:\n",
|
||
" raise ValueError(\"Inner dimensions must match: \"\n",
|
||
" f\"{n_cols_A} != {n_rows_B}\")\n",
|
||
"\n",
|
||
" # Transpose B once to make column access efficient\n",
|
||
" B_cols = list(zip(*B))\n",
|
||
"\n",
|
||
" # Compute product using list comprehensions\n",
|
||
" return [\n",
|
||
" [sum(a * b for a, b in zip(row, col)) for col in B_cols]\n",
|
||
" for row in A\n",
|
||
" ]\n",
|
||
"def matmul(A, B):\n",
|
||
" if not A or not B:\n",
|
||
" return []\n",
|
||
" m, p = len(A), len(A[0])\n",
|
||
" n = len(B[0])\n",
|
||
" # ensure inner dimension matches\n",
|
||
" result = [[0]*n for _ in range(m)]\n",
|
||
" for i in range(m):\n",
|
||
" for k in range(p):\n",
|
||
" aik = A[i][k]\n",
|
||
" for j in range(n):\n",
|
||
" result[i][j] += aik * B[k][j]\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" n = len(A)\n",
|
||
" m = len(B[0])\n",
|
||
" p = len(B)\n",
|
||
" return [[sum(A[i][k] * B[k][j] for k in range(p)) for j in range(m)] for i in range(n)]\n",
|
||
"def matmul(A, B):\n",
|
||
" # Basic check dims\n",
|
||
" n = len(A)\n",
|
||
" assert n > 0\n",
|
||
" m = len(A[0])\n",
|
||
" # B has size m x p\n",
|
||
" assert len(B) == m\n",
|
||
" p = len(B[0])\n",
|
||
" # Pre-allocate result\n",
|
||
" C = [[0]*p for _ in range(n)]\n",
|
||
" # Compute transpose of B for better locality\n",
|
||
" B_T = list(map(list, zip(*B)))\n",
|
||
" for i in range(n):\n",
|
||
" Ai = A[i]\n",
|
||
" Ci = C[i]\n",
|
||
" for j in range(p):\n",
|
||
" Bj = B_T[j]\n",
|
||
" s = 0\n",
|
||
" for k in range(m):\n",
|
||
" s += Ai[k] * Bj[k]\n",
|
||
" Ci[j] = s\n",
|
||
" return C\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Return the product of two matrices in Theta(m^3/mn)*n^2 time,\n",
|
||
" optimizing cache usage if --precache-multiple was selected.\n",
|
||
" \"\"\"\n",
|
||
" _check_input(A, B)\n",
|
||
" m = len(A); n = len(A[0]); k = len(B[0]); # (m x n) * (n x k) => (m x k)\n",
|
||
" _use_a = (m / n <= 100.0 * n / k)\n",
|
||
" M_local_cache_avail_prefs = sympy.cache.get('M_local_cache_avail_prefs', 0)\n",
|
||
" M_local_cache_avail_nonp = sympy.cache.get('M_local_cache_avail_nonp', 0)\n",
|
||
"\n",
|
||
" if sympy.cache and M_local_cache_avail_nonp and _use_a:\n",
|
||
" local_cache_key_A = (m,n,1)\n",
|
||
" local_cache_key_B = (n,k,1)\n",
|
||
" if local_cache_key_A not in sympy.cache:\n",
|
||
" sympy.cache[local_cache_key_A] = [(r,c) for r in range(m) for c in range(n)]\n",
|
||
" if local_cache_key_B not in sympy.cache:\n",
|
||
" sympy.cache[local_cache_key_B] = [(r,c) for r in range(n) for c in range(k)]\n",
|
||
" A_local, B_local = sympy.cache[local_cache_key_A], sympy.cache[local_cache_key_B]\n",
|
||
" else:\n",
|
||
" A_local, B_local = None, None\n",
|
||
"\n",
|
||
" def fast_matmul(A_local, B_local, _):\n",
|
||
" result = [[sum(A_local[i][j] * B_local[j][l] for j in range(n))\n",
|
||
" for l in range(k)]\n",
|
||
" for i in range(m)]\n",
|
||
" return result\n",
|
||
"\n",
|
||
" if A_local and B_local:\n",
|
||
" return fast_matmul(A_local, B_local, k)\n",
|
||
" else:\n",
|
||
" return fast_matmul(A, B, k)\n",
|
||
"def matmul(A, B):\n",
|
||
" n, m = len(A), len(B)\n",
|
||
" assert all(len(row)==m for row in A) and all(len(row)==len(B[0]) for row in B)\n",
|
||
" # maybe compute B transposed\n",
|
||
" BT = list(zip(*B))\n",
|
||
" result = [[sum(a*b for a,b in zip(row, col)) for col in BT] for row in A]\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" m = len(A)\n",
|
||
" n = len(A[0])\n",
|
||
" p = len(B[0])\n",
|
||
" # compute result matrix C(m x p)\n",
|
||
" result = [[sum(A[i][k]*B[k][j] for k in range(n)) for j in range(p)] for i in range(m)]\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" n = len(A)\n",
|
||
" m = len(B[0])\n",
|
||
" p = len(B)\n",
|
||
" result = [[0]*m for _ in range(n)]\n",
|
||
" for i in range(n):\n",
|
||
" Ai=A[i]\n",
|
||
" Ri=result[i]\n",
|
||
" for k in range(p):\n",
|
||
" aik=Ai[k]\n",
|
||
" Bk=B[k]\n",
|
||
" for j in range(m):\n",
|
||
" Ri[j]+=aik*Bk[j]\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A (n x m) and B (m x p) without using external libraries.\n",
|
||
" \"\"\"\n",
|
||
" n=len(A)\n",
|
||
" m=len(A[0])\n",
|
||
" p=len(B[0])\n",
|
||
" # Check compatibility\n",
|
||
" if len(B)!=m:\n",
|
||
" raise ValueError(\"Incompatible dimensions\")\n",
|
||
" # Transpose B for cache-friendly access\n",
|
||
" B_T=[list(col) for col in zip(*B)]\n",
|
||
" # Prepare result matrix\n",
|
||
" result=[[0]*p for _ in range(n)]\n",
|
||
" for i in range(n):\n",
|
||
" row=A[i]\n",
|
||
" # local assignments\n",
|
||
" res_row=result[i]\n",
|
||
" for j in range(p):\n",
|
||
" col=B_T[j]\n",
|
||
" s=0\n",
|
||
" for a, b in zip(row, col):\n",
|
||
" s += a*b\n",
|
||
" res_row[j]=s\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Multiply two matrices A (m x n) and B (n x p) using pure Python.\n",
|
||
"\n",
|
||
" Args:\n",
|
||
" A: list of m lists, each of length n.\n",
|
||
" B: list of n lists, each of length p.\n",
|
||
"\n",
|
||
" Returns:\n",
|
||
" C: list of m lists, each of length p, the product.\n",
|
||
" \"\"\"\n",
|
||
" m = len(A); n = len(A[0]); p = len(B[0])\n",
|
||
" # Preallocate result\n",
|
||
" C = [[0]*p for _ in range(m)]\n",
|
||
" # transpose B for better cache (although Python's memory model)\n",
|
||
" B_T = [list(col) for col in zip(*B)]\n",
|
||
" # iterate over rows of A and rows of B_T\n",
|
||
" for i in range(m):\n",
|
||
" Ai = A[i]\n",
|
||
" Ci = C[i]\n",
|
||
" for k in range(p):\n",
|
||
" s = 0\n",
|
||
" Bk = B_T[k]\n",
|
||
" for j in range(n):\n",
|
||
" s += Ai[j] * Bk[j]\n",
|
||
" Ci[k] = s\n",
|
||
" return C\n",
|
||
"def matmul(A, B):\n",
|
||
" # A: m x n, B: n x p\n",
|
||
" m, n = len(A), len(A[0])\n",
|
||
" n2, p = len(B), len(B[0])\n",
|
||
" assert n == n2\n",
|
||
" # Precompute columns of B\n",
|
||
" Bcols = list(zip(*B))\n",
|
||
" return [[sum(a*b for a,b in zip(row,c)) for c in Bcols] for row in A]\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices using pure Python.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : List[List[Number]]\n",
|
||
" The first matrix (m × n).\n",
|
||
" B : List[List[Number]]\n",
|
||
" The second matrix (n × p).\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" List[List[Number]]\n",
|
||
" The product matrix (m × p).\n",
|
||
"\n",
|
||
" Raises\n",
|
||
" ------\n",
|
||
" ValueError\n",
|
||
" If the inner dimensions of A and B do not match.\n",
|
||
" \"\"\"\n",
|
||
" if not A or not B or not B[0]:\n",
|
||
" return []\n",
|
||
"\n",
|
||
" m = len(A)\n",
|
||
" n = len(A[0])\n",
|
||
" if len(B) != n:\n",
|
||
" raise ValueError(\"Inner dimensions must agree: A: {}, B: {}.\".format(n, len(B)))\n",
|
||
"\n",
|
||
" p = len(B[0])\n",
|
||
" # column count of B must be p\n",
|
||
" # Use list comprehensions for a compact, Python‑native implementation\n",
|
||
" return [[sum(A[i][k] * B[k][j] for k in range(n)) for j in range(p)] for i in range(m)]\n",
|
||
"def matmul(A, B):\n",
|
||
" ...\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" # matrix multiplication using only native Python\n",
|
||
" ...\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" n_rows = len(A)\n",
|
||
" n_cols = len(B[0])\n",
|
||
" k = len(B) # check match\n",
|
||
" if any(len(row)!=k for row in A):\n",
|
||
" raise ValueError(\"A dimensions don't match B\")\n",
|
||
" # transpose B for better cache\n",
|
||
" B_T = list(zip(*B)) # returns tuples but we can keep\n",
|
||
" result = [[0]*n_cols for _ in range(n_rows)]\n",
|
||
" for i in range(n_rows):\n",
|
||
" Ai = A[i]\n",
|
||
" Ri = result[i]\n",
|
||
" for j, Bj in enumerate(B_T):\n",
|
||
" s = 0\n",
|
||
" for a,b in zip(Ai, Bj):\n",
|
||
" s += a*b\n",
|
||
" Ri[j] = s\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" n = len(A)\n",
|
||
" m = len(B[0])\n",
|
||
" p = len(B)\n",
|
||
" # assert p == len(A[0])? we can compute\n",
|
||
" result = [[0]*m for _ in range(n)]\n",
|
||
" for i in range(n):\n",
|
||
" ai = A[i]\n",
|
||
" for k in range(p):\n",
|
||
" aik = ai[k]\n",
|
||
" if aik:\n",
|
||
" bk = B[k]\n",
|
||
" for j in range(m):\n",
|
||
" result[i][j] += aik * bk[j]\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" # Ensure both are lists of lists, etc. \n",
|
||
" return [[sum(a*b for a,b in zip(row,col)) for col in zip(*B)] for row in A]\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"None\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiplies two matrices A and B using pure Python lists.\n",
|
||
" Expects A to be m x n and B to be n x p.\n",
|
||
" Returns the resulting m x p matrix.\n",
|
||
" \"\"\"\n",
|
||
" return [[sum(a * b for a, b in zip(rowA, colB)) for colB in zip(*B)] for rowA in A]\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B using only native Python constructs.\n",
|
||
" \n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list[list[Number]]\n",
|
||
" Left‑hand matrix.\n",
|
||
" B : list[list[Number]]\n",
|
||
" Right‑hand matrix.\n",
|
||
" \n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" list[list[Number]]\n",
|
||
" The product matrix A * B.\n",
|
||
" \"\"\"\n",
|
||
" # Transpose B to ease column access\n",
|
||
" Bt = list(zip(*B))\n",
|
||
" # Compute each entry as the dot product of a row of A and a column of B\n",
|
||
" return [[sum(a * b for a, b in zip(row, col))\n",
|
||
" for col in Bt] for row in A]\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" # assume A: m x n, B: n x p\n",
|
||
" n = len(A)\n",
|
||
" m = len(A[0])\n",
|
||
" p = len(B[0])\n",
|
||
" # precompute columns of B via zip\n",
|
||
" columns_B = list(zip(*B))\n",
|
||
" result = [[sum(a*b for a,b in zip(row, col)) for col in columns_B] for row in A]\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B using plain Python.\n",
|
||
" A : list of m rows, each a list of p numbers\n",
|
||
" B : list of p rows, each a list of n numbers\n",
|
||
" Returns a list of m rows, each a list of n numbers\n",
|
||
" \"\"\"\n",
|
||
" m, p = len(A), len(A[0]) # dimensions of A\n",
|
||
" assert p == len(B), \"Incompatible matrix dimensions\"\n",
|
||
" n = len(B[0]) # number of columns of B\n",
|
||
"\n",
|
||
" # initialise result matrix with zeros\n",
|
||
" C = [[0] * n for _ in range(m)]\n",
|
||
"\n",
|
||
" # iterate over the shared dimension first\n",
|
||
" for k in range(p):\n",
|
||
" B_row = B[k]\n",
|
||
" for i in range(m):\n",
|
||
" aik = A[i][k]\n",
|
||
" if aik: # skip multiplies by zero\n",
|
||
" C_row = C[i]\n",
|
||
" # the inner loop that does the real work\n",
|
||
" for j in range(n):\n",
|
||
" C_row[j] += aik * B_row[j]\n",
|
||
" return C\n",
|
||
"def matmul(A, B):\n",
|
||
" m = len(A); n = len(A[0]); p = len(B[0])\n",
|
||
" # validate B has proper shape\n",
|
||
" result = [[0]*p for _ in range(m)]\n",
|
||
" for i in range(m):\n",
|
||
" rowA = A[i]\n",
|
||
" row_res = result[i]\n",
|
||
" for k in range(n):\n",
|
||
" aik = rowA[k]\n",
|
||
" if aik:\n",
|
||
" rowBk = B[k]\n",
|
||
" for j in range(p):\n",
|
||
" row_res[j] += aik * rowBk[j]\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" if not A or not B:\n",
|
||
" return []\n",
|
||
" n, m = len(A), len(A[0])\n",
|
||
" p, q = len(B), len(B[0])\n",
|
||
" if m != p:\n",
|
||
" raise ValueError(\"Inner matrix dimensions must agree.\")\n",
|
||
" # compute C with zeros\n",
|
||
" C = [[0]*q for _ in range(n)]\n",
|
||
" for i in range(n):\n",
|
||
" Ai = A[i]\n",
|
||
" Ci = C[i]\n",
|
||
" for k in range(m):\n",
|
||
" aik = Ai[k]\n",
|
||
" Bk = B[k]\n",
|
||
" for j in range(q):\n",
|
||
" Ci[j] += aik * Bk[j]\n",
|
||
" return C\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A (n × p) and B (p × m) using a cache‑friendly\n",
|
||
" block‑style algorithm that reduces Python overhead compared to a\n",
|
||
" straightforward triple loop.\n",
|
||
" \"\"\"\n",
|
||
" n = len(A) # rows of A\n",
|
||
" p = len(B) # shared dimension\n",
|
||
" m = len(B[0]) # columns of B\n",
|
||
"\n",
|
||
" # Result matrix initialised with zeros\n",
|
||
" C = [[0] * m for _ in range(n)]\n",
|
||
"\n",
|
||
" # Optimised loop ordering: i → k → j\n",
|
||
" for i in range(n):\n",
|
||
" Ai = A[i]\n",
|
||
" Ci = C[i]\n",
|
||
" for k in range(p):\n",
|
||
" aik = Ai[k]\n",
|
||
" if aik: # skip zero multiplications\n",
|
||
" Bk = B[k]\n",
|
||
" for j in range(m):\n",
|
||
" Ci[j] += aik * Bk[j]\n",
|
||
" return C\n",
|
||
"def matmul(A, B):\n",
|
||
" # ensure convertible shapes\n",
|
||
" m, n = len(A), len(A[0])\n",
|
||
" p = len(B[0])\n",
|
||
" # Precompute transpose of B to improve cache locality\n",
|
||
" BT = list(zip(*B))\n",
|
||
" result = [[0]*p for _ in range(m)]\n",
|
||
" for i in range(m):\n",
|
||
" Ai = A[i]\n",
|
||
" Ri = result[i]\n",
|
||
" for j, Bj in enumerate(BT):\n",
|
||
" s = 0\n",
|
||
" for k in range(n):\n",
|
||
" s += Ai[k] * Bj[k]\n",
|
||
" Ri[j] = s\n",
|
||
" return result\n",
|
||
"None\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"None\n",
|
||
"None\n",
|
||
"None\n",
|
||
"None\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" # ensure shape\n",
|
||
" if not A: return []\n",
|
||
" m, k = len(A), len(A[0])\n",
|
||
" k2, n = len(B), len(B[0])\n",
|
||
" assert k == k2\n",
|
||
" # transpose B\n",
|
||
" B_T = list(zip(*B))\n",
|
||
" # compute\n",
|
||
" return [[sum(a*b for a,b in zip(row, col)) for col in B_T] for row in A]\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" # A is an m x n matrix, B is an n x p matrix\n",
|
||
" m = len(A)\n",
|
||
" n = len(A[0]) if A else 0\n",
|
||
" p = len(B[0]) if B else 0\n",
|
||
"\n",
|
||
" # In case the dimensions are incompatible, raise an error\n",
|
||
" if n != len(B):\n",
|
||
" raise ValueError(\"Incompatible matrix dimensions: A has %d cols but B has %d rows.\" % (n, len(B)))\n",
|
||
"\n",
|
||
" # Prepare the result matrix filled with zeros\n",
|
||
" C = [[0] * p for _ in range(m)]\n",
|
||
"\n",
|
||
" # Perform the multiplication using a cache-friendly triple loop\n",
|
||
" for i in range(m):\n",
|
||
" Ai = A[i]\n",
|
||
" Ci = C[i]\n",
|
||
" for k in range(n):\n",
|
||
" aik = Ai[k]\n",
|
||
" Bk = B[k]\n",
|
||
" for j in range(p):\n",
|
||
" Ci[j] += aik * Bk[j]\n",
|
||
" return C\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B using plain Python lists.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list[list[float]]\n",
|
||
" Left matrix of shape (m, n).\n",
|
||
" B : list[list[float]]\n",
|
||
" Right matrix of shape (n, p).\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" list[list[float]]\n",
|
||
" The product matrix of shape (m, p).\n",
|
||
"\n",
|
||
" Raises\n",
|
||
" ------\n",
|
||
" ValueError\n",
|
||
" If the inner dimensions do not agree.\n",
|
||
" \"\"\"\n",
|
||
" # Validate input\n",
|
||
" if not A or not B:\n",
|
||
" return []\n",
|
||
"\n",
|
||
" m, n_A = len(A), len(A[0])\n",
|
||
" n_B, p = len(B), len(B[0])\n",
|
||
"\n",
|
||
" if n_A != n_B:\n",
|
||
" raise ValueError(\"Inner matrix dimensions must agree: \"\n",
|
||
" f\"{n_A} != {n_B}\")\n",
|
||
"\n",
|
||
" # Pre‑allocate result matrix with zeros\n",
|
||
" C = [[0.0 for _ in range(p)] for _ in range(m)]\n",
|
||
"\n",
|
||
" # Classic triple‑loop multiplication\n",
|
||
" for i in range(m):\n",
|
||
" Ai = A[i]\n",
|
||
" Ci = C[i]\n",
|
||
" for k in range(n_A):\n",
|
||
" aik = Ai[k]\n",
|
||
" Bk = B[k]\n",
|
||
" # Unroll the inner loop over p\n",
|
||
" for j in range(p):\n",
|
||
" Ci[j] += aik * Bk[j]\n",
|
||
"\n",
|
||
" return C\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiplies two matrices A and B represented as lists of lists using\n",
|
||
" plain Python code. Handles generic rectangular matrices.\n",
|
||
" \"\"\"\n",
|
||
" # Basic size validation\n",
|
||
" if not A or not B or not A[0] or not B[0]:\n",
|
||
" raise ValueError(\"Matrices cannot be empty\")\n",
|
||
" rows_a = len(A)\n",
|
||
" cols_a = len(A[0])\n",
|
||
" rows_b = len(B)\n",
|
||
" cols_b = len(B[0])\n",
|
||
"\n",
|
||
" if cols_a != rows_b:\n",
|
||
" raise ValueError(\"Inner dimensions must match for multiplication\")\n",
|
||
"\n",
|
||
" # Compute the product using a straightforward triple loop\n",
|
||
" result = [\n",
|
||
" [sum(A[i][k] * B[k][j] for k in range(cols_a)) for j in range(cols_b)]\n",
|
||
" for i in range(rows_a)\n",
|
||
" ]\n",
|
||
"\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices using a naïve algorithm implemented in pure Python.\n",
|
||
" \"\"\"\n",
|
||
" # Get dimensions\n",
|
||
" na = len(A)\n",
|
||
" ma = len(A[0]) if A else 0\n",
|
||
" nb = len(B)\n",
|
||
" mb = len(B[0]) if B else 0\n",
|
||
" \n",
|
||
" if ma != nb:\n",
|
||
" raise ValueError(\"Inner dimensions must match for multiplication.\")\n",
|
||
" \n",
|
||
" # Create result matrix\n",
|
||
" result = [[0 for _ in range(mb)] for _ in range(na)]\n",
|
||
" \n",
|
||
" # Standard triple‑loop multiplication\n",
|
||
" for i in range(na):\n",
|
||
" Ai = A[i]\n",
|
||
" for j in range(mb):\n",
|
||
" sum = 0\n",
|
||
" for k in range(ma):\n",
|
||
" sum += Ai[k] * B[k][j]\n",
|
||
" result[i][j] = sum\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B and return the product.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list[list[Number]]\n",
|
||
" Left matrix of shape (m, n).\n",
|
||
" B : list[list[Number]]\n",
|
||
" Right matrix of shape (n, p).\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" C : list[list[Number]]\n",
|
||
" Matrix product of shape (m, p).\n",
|
||
"\n",
|
||
" Raises\n",
|
||
" ------\n",
|
||
" ValueError\n",
|
||
" If the input matrices cannot be multiplied due to incompatible shapes.\n",
|
||
" \"\"\"\n",
|
||
" # Validate inputs\n",
|
||
" if not A or not B:\n",
|
||
" return []\n",
|
||
"\n",
|
||
" # Dimensions\n",
|
||
" m, n = len(A), len(A[0]) if A else 0\n",
|
||
" n_b, p = len(B), len(B[0]) if B else 0\n",
|
||
"\n",
|
||
" if n != n_b:\n",
|
||
" raise ValueError(f\"Incompatible dimensions: A is {m}x{n}, B is {n_b}x{p}\")\n",
|
||
"\n",
|
||
" # Pre-allocate result matrix with zeros\n",
|
||
" C = [[0] * p for _ in range(m)]\n",
|
||
"\n",
|
||
" # Main multiplication loop\n",
|
||
" for i in range(m):\n",
|
||
" a_row = A[i]\n",
|
||
" c_row = C[i]\n",
|
||
" for k in range(n):\n",
|
||
" aik = a_row[k]\n",
|
||
" if aik == 0:\n",
|
||
" continue # Skip multiplication by zero\n",
|
||
" b_row_k = B[k]\n",
|
||
" # Unroll the inner loop for potential speed\n",
|
||
" for j in range(p):\n",
|
||
" c_row[j] += aik * b_row_k[j]\n",
|
||
" return C\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Multiply two matrices using only native Python lists.\"\"\"\n",
|
||
" # Basic dimension checks\n",
|
||
" if not A or not B or not A[0] or not B[0]:\n",
|
||
" raise ValueError(\"Input matrices must be non-empty\")\n",
|
||
" if len(A[0]) != len(B):\n",
|
||
" raise ValueError(\"Number of columns in A must equal number of rows in B\")\n",
|
||
"\n",
|
||
" # Transpose B to get its columns efficiently\n",
|
||
" BT = list(zip(*B)) # each is a tuple: column of B\n",
|
||
"\n",
|
||
" # Compute the product\n",
|
||
" result = [[sum(a * b for a, b in zip(row, col)) for col in BT] for row in A]\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" m = len(A)\n",
|
||
" p = len(A[0])\n",
|
||
" if p==0:\n",
|
||
" return [[] for _ in range(m)]\n",
|
||
" n = len(B[0])\n",
|
||
" # transpose B for cache\n",
|
||
" Bt = [[B[i][j] for i in range(p)] for j in range(n)]\n",
|
||
" res = [[0]*n for _ in range(m)]\n",
|
||
" for i in range(m):\n",
|
||
" Ai = A[i]\n",
|
||
" Ri = res[i]\n",
|
||
" for k in range(p):\n",
|
||
" aik = Ai[k]\n",
|
||
" Bk = Bt # not right; we need to use Bt[j][k].\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" ...\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" # A: m x n, B: n x p\n",
|
||
" m, n = len(A), len(A[0])\n",
|
||
" assert n == len(B), \"Incompatible matrices\"\n",
|
||
" p = len(B[0])\n",
|
||
" # pre-transpose B to speed up\n",
|
||
" B_T = list(map(list, zip(*B))) # p x n\n",
|
||
" return [[sum(a*b for a, b in zip(row, col)) for col in B_T] for row in A]\n",
|
||
"None\n",
|
||
"def matmul(A, B): return ...\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Return `A * B` for two 2‑D lists `A` and `B` using pure Python.\"\"\"\n",
|
||
" # Ensure dimensions are compatible\n",
|
||
" if not A or not B or not B[0]:\n",
|
||
" return []\n",
|
||
"\n",
|
||
" # Transpose B once to obtain column access in O(1)\n",
|
||
" B_t = list(zip(*B))\n",
|
||
"\n",
|
||
" # Compute the matrix product using list comprehensions\n",
|
||
" return [\n",
|
||
" [sum(a * b for a, b in zip(row, col))\n",
|
||
" for col in B_t] # compute dot product of row with each column of B\n",
|
||
" for row in A\n",
|
||
" ]\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Compute the matrix product C = A @ B with pure Python.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : List[List[float]]\n",
|
||
" Left matrix of size m × p.\n",
|
||
" B : List[List[float]]\n",
|
||
" Right matrix of size p × n.\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" List[List[float]]\n",
|
||
" Resulting matrix of size m × n.\n",
|
||
" \"\"\"\n",
|
||
" m, pA = len(A), len(A[0])\n",
|
||
" pB, n = len(B), len(B[0])\n",
|
||
"\n",
|
||
" if pA != pB:\n",
|
||
" raise ValueError(\"Inner matrix dimensions must agree (got %d×%d and %d×%d) \"\n",
|
||
" % (m, pA, pB, n))\n",
|
||
"\n",
|
||
" # Allocate result matrix\n",
|
||
" C = [[0.0] * n for _ in range(m)]\n",
|
||
"\n",
|
||
" # Blocked matrix multiplication for better cache locality.\n",
|
||
" # Choose a block size that works well on most systems\n",
|
||
" block = 64\n",
|
||
"\n",
|
||
" for i0 in range(0, m, block):\n",
|
||
" i_max = min(i0 + block, m)\n",
|
||
" for k0 in range(0, pA, block):\n",
|
||
" k_max = min(k0 + block, pA)\n",
|
||
" for j0 in range(0, n, block):\n",
|
||
" j_max = min(j0 + block, n)\n",
|
||
"\n",
|
||
" for i in range(i0, i_max):\n",
|
||
" ai = A[i]\n",
|
||
" ci = C[i]\n",
|
||
" for k in range(k0, k_max):\n",
|
||
" aik = ai[k]\n",
|
||
" bk = B[k]\n",
|
||
" for j in range(j0, j_max):\n",
|
||
" ci[j] += aik * bk[j]\n",
|
||
" return C\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" if not A or not B:\n",
|
||
" return []\n",
|
||
" m = len(A)\n",
|
||
" n = len(A[0])\n",
|
||
" p = len(B[0])\n",
|
||
" # check compatibility: len(B)==n\n",
|
||
" # compute result matrix with nested loops\n",
|
||
" res = [[0]*p for _ in range(m)]\n",
|
||
" for i in range(m):\n",
|
||
" Ai = A[i]\n",
|
||
" for j in range(p):\n",
|
||
" s = 0\n",
|
||
" for k in range(n):\n",
|
||
" s += Ai[k]*B[k][j]\n",
|
||
" res[i][j] = s\n",
|
||
" return res\n",
|
||
"def matmul(A, B):\n",
|
||
" # check dimensions\n",
|
||
" ...\n",
|
||
" # compute product\n",
|
||
"def matmul(A, B):\n",
|
||
" # Extract dimensions\n",
|
||
" if not A or not B or not A[0] or not B[0]:\n",
|
||
" return [] # or raise ValueError...\n",
|
||
" # Determine dimensions\n",
|
||
" p = len(A[0]) # columns of A, rows of B\n",
|
||
" if p != len(B):\n",
|
||
" raise ValueError(\"Incompatible matrix sizes.\")\n",
|
||
" # Transpose B for efficient column access\n",
|
||
" BT = list(zip(*B))\n",
|
||
" # Perform multiplication\n",
|
||
" result = []\n",
|
||
" for row in A:\n",
|
||
" new_row = []\n",
|
||
" for col in BT:\n",
|
||
" # Dot product\n",
|
||
" sum_val = 0\n",
|
||
" for a, b in zip(row, col):\n",
|
||
" sum_val += a * b\n",
|
||
" new_row.append(sum_val)\n",
|
||
" result.append(new_row)\n",
|
||
" return result\n",
|
||
"def matmul(A, B):\n",
|
||
" # optimize: transpose B\n",
|
||
" BT = list(zip(*B)) # tuple of tuples (row of B^T)\n",
|
||
" return [[sum(a*b for a, b in zip(rowA, colB)) for colB in BT] for rowA in A]\n",
|
||
"def matmul(A, B):\n",
|
||
" n = len(A)\n",
|
||
" m = len(B[0])\n",
|
||
" p = len(B)\n",
|
||
" return [[sum(A[i][k]*B[k][j] for k in range(p)) for j in range(m)] for i in range(n)]\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"\n",
|
||
" Multiply two matrices A and B using pure Python.\n",
|
||
"\n",
|
||
" Parameters\n",
|
||
" ----------\n",
|
||
" A : list[list[float | int | complex]]\n",
|
||
" The first matrix of dimensions (m, p).\n",
|
||
" B : list[list[float | int | complex]]\n",
|
||
" The second matrix of dimensions (p, n).\n",
|
||
"\n",
|
||
" Returns\n",
|
||
" -------\n",
|
||
" list[list[float | int | complex]]\n",
|
||
" The product matrix of dimensions (m, n).\n",
|
||
"\n",
|
||
" Raises\n",
|
||
" ------\n",
|
||
" ValueError\n",
|
||
" If the inner dimensions do not match.\n",
|
||
" \"\"\"\n",
|
||
" # Basic sanity checks for empty/corrupt inputs\n",
|
||
" if not A or not B:\n",
|
||
" raise ValueError(\"Input matrices cannot be empty\")\n",
|
||
"\n",
|
||
" p = len(A[0])\n",
|
||
" for row in A:\n",
|
||
" if len(row) != p:\n",
|
||
" raise ValueError(\"All rows in A must have the same length\")\n",
|
||
" q = len(B)\n",
|
||
" for row in B:\n",
|
||
" if len(row) != len(B[0]):\n",
|
||
" raise ValueError(\"All rows in B must have the same length\")\n",
|
||
"\n",
|
||
" # Ensure the inner dimensions match\n",
|
||
" if p != q:\n",
|
||
" raise ValueError(\"Inner matrix dimensions must agree: len(A[0]) != len(B)\")\n",
|
||
"\n",
|
||
" # Transpose B to avoid repeated look‑ups in the inner loop\n",
|
||
" B_T = list(zip(*B)) # Each element is a tuple representing a column\n",
|
||
"\n",
|
||
" # Perform matrix multiplication\n",
|
||
" return [[sum(a * b for a, b in zip(row, col)) for col in B_T] for row in A]\n",
|
||
"def matmul(A, B):\n",
|
||
" \"\"\"Return the matrix product of A and B using native Python.\"\"\"\n",
|
||
" # Transpose B once to avoid repeated column lookups.\n",
|
||
" B_T = list(zip(*B))\n",
|
||
" # Compute each element of the product using a generator expression.\n",
|
||
" return [[sum(a * b for a, b in zip(row, col)) for col in B_T] for row in A]\n",
|
||
"None\n",
|
||
"None\n",
|
||
"None\n",
|
||
"None\n",
|
||
"def matmul(A, B):\n",
|
||
" if not A or not B: \n",
|
||
" return []\n",
|
||
" nrowA = len(A)\n",
|
||
" ncolA = len(A[0])\n",
|
||
" nrowB = len(B)\n",
|
||
" ncolB = len(B[0])\n",
|
||
" if ncolA != nrowB:\n",
|
||
" raise ValueError(\"Incompatible dimensions for matrix multiplication\")\n",
|
||
" # Precompute columns of B\n",
|
||
" colsB = list(zip(*B))\n",
|
||
" return [\n",
|
||
" [sum(a*b for a, b in zip(row, col)) for col in colsB]\n",
|
||
" for row in A\n",
|
||
" ]\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"TrainOutput(global_step=100, training_loss=3.209321222243488e-05, metrics={'train_runtime': 5865.3354, 'train_samples_per_second': 0.034, 'train_steps_per_second': 0.017, 'total_flos': 0.0, 'train_loss': 3.209321222243488e-05})"
|
||
]
|
||
},
|
||
"execution_count": 32,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"trainer.train()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"And now with the LoRA we just trained with GRPO - we first save the LoRA first!"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": [
|
||
"model.save_pretrained(\"gemma_4_lora\") # Local saving\n",
|
||
"tokenizer.save_pretrained(\"gemma_4_lora\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Verify LoRA is actually trained!"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": [
|
||
"from safetensors import safe_open\n",
|
||
"\n",
|
||
"tensors = {}\n",
|
||
"with safe_open(\"grpo_saved_lora/adapter_model.safetensors\", framework = \"pt\") as f:\n",
|
||
" # Verify both A and B are non zero\n",
|
||
" for key in f.keys():\n",
|
||
" tensor = f.get_tensor(key)\n",
|
||
" n_zeros = (tensor == 0).sum() / tensor.numel()\n",
|
||
" assert(n_zeros.item() != tensor.numel())"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<a name=\"Inference\"></a>\n",
|
||
"# Inference\n",
|
||
"Now let's try the model we just trained!"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": [
|
||
"text = tokenizer.apply_chat_template(\n",
|
||
" [{\"role\": \"user\", \"content\": prompt.strip()}],\n",
|
||
" tokenize = False,\n",
|
||
" add_generation_prompt = True,\n",
|
||
")\n",
|
||
"\n",
|
||
"from transformers import TextStreamer\n",
|
||
"\n",
|
||
"_ = model.generate(\n",
|
||
" **tokenizer(images = None, text = text, return_tensors = \"pt\").to(\"cuda\"),\n",
|
||
" temperature = 1.0, top_p = 0.95, top_k = 64,\n",
|
||
" max_new_tokens = 1024,\n",
|
||
" streamer = TextStreamer(tokenizer, skip_prompt = False),\n",
|
||
")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<a name=\"Save\"></a>\n",
|
||
"### Saving to float16 for VLLM\n",
|
||
"\n",
|
||
"We also support saving to `float16` directly. Select `merged_16bit` for float16 or `merged_4bit` for int4. We also allow `lora` adapters as a fallback. Use `push_to_hub_merged` to upload to your Hugging Face account! You can go to https://huggingface.co/settings/tokens for your personal tokens. See [our docs](https://unsloth.ai/docs/basics/inference-and-deployment) for more deployment options."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": [
|
||
"# Merge to 16bit\n",
|
||
"if False: model.save_pretrained_merged(\"gemma_4_finetune_16bit\", tokenizer, save_method = \"merged_16bit\",)\n",
|
||
"if False: model.push_to_hub_merged(\"HF_USERNAME/gemma_4_finetune_16bit\", tokenizer, save_method = \"merged_16bit\", token = \"YOUR_HF_TOKEN\")\n",
|
||
"\n",
|
||
"# Merge to 4bit\n",
|
||
"if False: model.save_pretrained_merged(\"gemma_4_finetune_4bit\", tokenizer, save_method = \"merged_4bit\",)\n",
|
||
"if False: model.push_to_hub_merged(\"HF_USERNAME/gemma_4_finetune_4bit\", tokenizer, save_method = \"merged_4bit\", token = \"YOUR_HF_TOKEN\")\n",
|
||
"\n",
|
||
"# Just LoRA adapters\n",
|
||
"if False:\n",
|
||
" model.save_pretrained(\"gemma_4_lora\")\n",
|
||
" tokenizer.save_pretrained(\"gemma_4_lora\")\n",
|
||
"if False:\n",
|
||
" model.push_to_hub(\"HF_USERNAME/gemma_4_lora\", token = \"YOUR_HF_TOKEN\")\n",
|
||
" tokenizer.push_to_hub(\"HF_USERNAME/gemma_4_lora\", token = \"YOUR_HF_TOKEN\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### GGUF / llama.cpp Conversion\n",
|
||
"To save to `GGUF` / `llama.cpp`, we support it natively now! We clone `llama.cpp` and we default save it to `q8_0`. We allow all methods like `q4_k_m`. Use `save_pretrained_gguf` for local saving and `push_to_hub_gguf` for uploading to HF.\n",
|
||
"\n",
|
||
"Some supported quant methods (full list on our [docs page](https://unsloth.ai/docs/basics/inference-and-deployment/saving-to-gguf)):\n",
|
||
"* `q8_0` - Fast conversion. High resource use, but generally acceptable.\n",
|
||
"* `q4_k_m` - Recommended. Uses Q6_K for half of the attention.wv and feed_forward.w2 tensors, else Q4_K.\n",
|
||
"* `q5_k_m` - Recommended. Uses Q6_K for half of the attention.wv and feed_forward.w2 tensors, else Q5_K.\n",
|
||
"\n",
|
||
"[**NEW**] To finetune and auto export to Ollama, try our [Ollama notebook](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3_(8B)-Ollama.ipynb)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"metadata": {},
|
||
"execution_count": null,
|
||
"outputs": [],
|
||
"source": [
|
||
"# Save to 8bit Q8_0\n",
|
||
"if False: model.save_pretrained_gguf(\"gemma_4_finetune\", tokenizer,)\n",
|
||
"# Remember to go to https://huggingface.co/settings/tokens for a token!\n",
|
||
"# And change hf to your username!\n",
|
||
"if False: model.push_to_hub_gguf(\"HF_USERNAME/gemma_4_finetune\", tokenizer, token = \"YOUR_HF_TOKEN\")\n",
|
||
"\n",
|
||
"# Save to 16bit GGUF\n",
|
||
"if False: model.save_pretrained_gguf(\"gemma_4_finetune\", tokenizer, quantization_method = \"f16\")\n",
|
||
"if False: model.push_to_hub_gguf(\"HF_USERNAME/gemma_4_finetune\", tokenizer, quantization_method = \"f16\", token = \"YOUR_HF_TOKEN\")\n",
|
||
"\n",
|
||
"# Save to q4_k_m GGUF\n",
|
||
"if False: model.save_pretrained_gguf(\"gemma_4_finetune\", tokenizer, quantization_method = \"q4_k_m\")\n",
|
||
"if False: model.push_to_hub_gguf(\"HF_USERNAME/gemma_4_finetune\", tokenizer, quantization_method = \"q4_k_m\", token = \"YOUR_HF_TOKEN\")\n",
|
||
"\n",
|
||
"# Save to multiple GGUF options - much faster if you want multiple!\n",
|
||
"if False:\n",
|
||
" model.push_to_hub_gguf(\n",
|
||
" \"HF_USERNAME/gemma_4_finetune\", # Change hf to your username!\n",
|
||
" tokenizer,\n",
|
||
" quantization_method = [\"q4_k_m\", \"q8_0\", \"q5_k_m\",],\n",
|
||
" token = \"YOUR_HF_TOKEN\",\n",
|
||
" )"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Now, use the `gemma_4_finetune.Q8_0.gguf` file or `gemma_4_finetune.Q4_K_M.gguf` file in llama.cpp.\n",
|
||
"\n",
|
||
"And we're done! If you have any questions on Unsloth, we have a [Discord](https://discord.gg/unsloth) channel! If you find any bugs or want to keep updated with the latest LLM stuff, or need help, join projects etc, feel free to join our Discord!\n",
|
||
"\n",
|
||
"Some other resources:\n",
|
||
"1. Train your own reasoning model - Llama GRPO notebook [Free Colab](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.1_(8B)-GRPO.ipynb)\n",
|
||
"2. Saving finetunes to Ollama. [Free notebook](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3_(8B)-Ollama.ipynb)\n",
|
||
"3. Llama 3.2 Vision finetuning - Radiography use case. [Free Colab](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.2_(11B)-Vision.ipynb)\n",
|
||
"4. See notebooks for DPO, ORPO, Continued pretraining, conversational finetuning and more on our [documentation](https://unsloth.ai/docs/get-started/unsloth-notebooks)!\n",
|
||
"\n",
|
||
"<div class=\"align-center\">\n",
|
||
" <a href=\"https://unsloth.ai\"><img src=\"https://github.com/unslothai/unsloth/raw/main/images/unsloth%20new%20logo.png\" width=\"115\"></a>\n",
|
||
" <a href=\"https://discord.gg/unsloth\"><img src=\"https://github.com/unslothai/unsloth/raw/main/images/Discord.png\" width=\"145\"></a>\n",
|
||
" <a href=\"https://unsloth.ai/docs/\"><img src=\"https://github.com/unslothai/unsloth/blob/main/images/documentation%20green%20button.png?raw=true\" width=\"125\"></a>\n",
|
||
"\n",
|
||
" Join Discord if you need help + ⭐️ <i>Star us on <a href=\"https://github.com/unslothai/unsloth\">Github</a> </i> ⭐️\n",
|
||
"</div>\n",
|
||
"\n",
|
||
" This notebook and all Unsloth notebooks are licensed [LGPL-3.0](https://github.com/unslothai/notebooks?tab=LGPL-3.0-1-ov-file#readme)."
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"accelerator": "GPU",
|
||
"colab": {
|
||
"gpuType": "T4",
|
||
"provenance": []
|
||
},
|
||
"kernelspec": {
|
||
"display_name": "Python 3",
|
||
"name": "python3"
|
||
},
|
||
"language_info": {
|
||
"name": "python"
|
||
},
|
||
"widgets": {
|
||
"application/vnd.jupyter.widget-state+json": {
|
||
"state": {}
|
||
}
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 0
|
||
}
|