Module 00_setup migration: Core functionality complete, NBGrader architecture issue discovered

 COMPLETED:
- Instructor solution executes perfectly
- NBDev export works (fixed import directives)
- Package functionality verified
- Student assignment generation works
- CLI integration complete
- Systematic testing framework established

⚠️ CRITICAL DISCOVERY:
- NBGrader requires cell metadata architecture changes
- Current generator creates content correctly but wrong cell types
- Would require major rework of assignment generation pipeline

📊 STATUS:
- Core TinyTorch functionality:  READY FOR STUDENTS
- NBGrader integration: Requires Phase 2 rework
- Ready to continue systematic testing of modules 01-06

🔧 FIXES APPLIED:
- Added #| export directive to imports in enhanced modules
- Fixed generator logic for student scaffolding
- Updated testing framework and documentation
This commit is contained in:
Vijay Janapa Reddi
2025-07-12 09:08:45 -04:00
parent 77030a0009
commit 77150be3a6
23 changed files with 11671 additions and 258 deletions

View File

@@ -0,0 +1,471 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "0cf257dc",
"metadata": {
"cell_marker": "\"\"\""
},
"source": [
"# Module 1: Tensor - Enhanced with nbgrader Support\n",
"\n",
"This is an enhanced version of the tensor module that demonstrates dual-purpose content creation:\n",
"- **Self-learning**: Rich educational content with guided implementation\n",
"- **Auto-grading**: nbgrader-compatible assignments with hidden tests\n",
"\n",
"## Dual System Benefits\n",
"\n",
"1. **Single Source**: One file generates both learning and assignment materials\n",
"2. **Consistent Quality**: Same instructor solutions in both contexts\n",
"3. **Flexible Assessment**: Choose between self-paced learning or formal grading\n",
"4. **Scalable**: Handle large courses with automated feedback\n",
"\n",
"## How It Works\n",
"\n",
"- **TinyTorch markers**: `#| exercise_start/end` for educational content\n",
"- **nbgrader markers**: `### BEGIN/END SOLUTION` for auto-grading\n",
"- **Hidden tests**: `### BEGIN/END HIDDEN TESTS` for automatic verification\n",
"- **Dual generation**: One command creates both student notebooks and assignments"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dbe77981",
"metadata": {},
"outputs": [],
"source": [
"#| default_exp core.tensor"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7dc4f1a0",
"metadata": {},
"outputs": [],
"source": [
"#| export\n",
"import numpy as np\n",
"from typing import Union, List, Tuple, Optional"
]
},
{
"cell_type": "markdown",
"id": "1765d8cb",
"metadata": {
"cell_marker": "\"\"\"",
"lines_to_next_cell": 1
},
"source": [
"## Enhanced Tensor Class\n",
"\n",
"This implementation shows how to create dual-purpose educational content:\n",
"\n",
"### For Self-Learning Students\n",
"- Rich explanations and step-by-step guidance\n",
"- Detailed hints and examples\n",
"- Progressive difficulty with scaffolding\n",
"\n",
"### For Formal Assessment\n",
"- Auto-graded with hidden tests\n",
"- Immediate feedback on correctness\n",
"- Partial credit for complex methods"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "aff9a0f2",
"metadata": {
"lines_to_next_cell": 1
},
"outputs": [],
"source": [
"#| export\n",
"class Tensor:\n",
" \"\"\"\n",
" TinyTorch Tensor: N-dimensional array with ML operations.\n",
" \n",
" This enhanced version demonstrates dual-purpose educational content\n",
" suitable for both self-learning and formal assessment.\n",
" \"\"\"\n",
" \n",
" def __init__(self, data: Union[int, float, List, np.ndarray], dtype: Optional[str] = None):\n",
" \"\"\"\n",
" Create a new tensor from data.\n",
" \n",
" Args:\n",
" data: Input data (scalar, list, or numpy array)\n",
" dtype: Data type ('float32', 'int32', etc.). Defaults to auto-detect.\n",
" \"\"\"\n",
" #| exercise_start\n",
" #| hint: Use np.array() to convert input data to numpy array\n",
" #| solution_test: tensor.shape should match input shape\n",
" #| difficulty: easy\n",
" \n",
" ### BEGIN SOLUTION\n",
" # Convert input to numpy array\n",
" if isinstance(data, (int, float)):\n",
" self._data = np.array(data)\n",
" elif isinstance(data, list):\n",
" self._data = np.array(data)\n",
" elif isinstance(data, np.ndarray):\n",
" self._data = data.copy()\n",
" else:\n",
" self._data = np.array(data)\n",
" \n",
" # Apply dtype conversion if specified\n",
" if dtype is not None:\n",
" self._data = self._data.astype(dtype)\n",
" ### END SOLUTION\n",
" \n",
" #| exercise_end\n",
" \n",
" @property\n",
" def data(self) -> np.ndarray:\n",
" \"\"\"Access underlying numpy array.\"\"\"\n",
" #| exercise_start\n",
" #| hint: Return the stored numpy array (_data attribute)\n",
" #| solution_test: tensor.data should return numpy array\n",
" #| difficulty: easy\n",
" \n",
" ### BEGIN SOLUTION\n",
" return self._data\n",
" ### END SOLUTION\n",
" \n",
" #| exercise_end\n",
" \n",
" @property\n",
" def shape(self) -> Tuple[int, ...]:\n",
" \"\"\"Get tensor shape.\"\"\"\n",
" #| exercise_start\n",
" #| hint: Use the .shape attribute of the numpy array\n",
" #| solution_test: tensor.shape should return tuple of dimensions\n",
" #| difficulty: easy\n",
" \n",
" ### BEGIN SOLUTION\n",
" return self._data.shape\n",
" ### END SOLUTION\n",
" \n",
" #| exercise_end\n",
" \n",
" @property\n",
" def size(self) -> int:\n",
" \"\"\"Get total number of elements.\"\"\"\n",
" #| exercise_start\n",
" #| hint: Use the .size attribute of the numpy array\n",
" #| solution_test: tensor.size should return total element count\n",
" #| difficulty: easy\n",
" \n",
" ### BEGIN SOLUTION\n",
" return self._data.size\n",
" ### END SOLUTION\n",
" \n",
" #| exercise_end\n",
" \n",
" @property\n",
" def dtype(self) -> np.dtype:\n",
" \"\"\"Get data type as numpy dtype.\"\"\"\n",
" #| exercise_start\n",
" #| hint: Use the .dtype attribute of the numpy array\n",
" #| solution_test: tensor.dtype should return numpy dtype\n",
" #| difficulty: easy\n",
" \n",
" ### BEGIN SOLUTION\n",
" return self._data.dtype\n",
" ### END SOLUTION\n",
" \n",
" #| exercise_end\n",
" \n",
" def __repr__(self) -> str:\n",
" \"\"\"String representation of the tensor.\"\"\"\n",
" #| exercise_start\n",
" #| hint: Format as \"Tensor([data], shape=shape, dtype=dtype)\"\n",
" #| solution_test: repr should include data, shape, and dtype\n",
" #| difficulty: medium\n",
" \n",
" ### BEGIN SOLUTION\n",
" data_str = self._data.tolist()\n",
" return f\"Tensor({data_str}, shape={self.shape}, dtype={self.dtype})\"\n",
" ### END SOLUTION\n",
" \n",
" #| exercise_end\n",
" \n",
" def add(self, other: 'Tensor') -> 'Tensor':\n",
" \"\"\"\n",
" Add two tensors element-wise.\n",
" \n",
" Args:\n",
" other: Another tensor to add\n",
" \n",
" Returns:\n",
" New tensor with element-wise sum\n",
" \"\"\"\n",
" #| exercise_start\n",
" #| hint: Use numpy's + operator for element-wise addition\n",
" #| solution_test: result should be new Tensor with correct values\n",
" #| difficulty: medium\n",
" \n",
" ### BEGIN SOLUTION\n",
" result_data = self._data + other._data\n",
" return Tensor(result_data)\n",
" ### END SOLUTION\n",
" \n",
" #| exercise_end\n",
" \n",
" def multiply(self, other: 'Tensor') -> 'Tensor':\n",
" \"\"\"\n",
" Multiply two tensors element-wise.\n",
" \n",
" Args:\n",
" other: Another tensor to multiply\n",
" \n",
" Returns:\n",
" New tensor with element-wise product\n",
" \"\"\"\n",
" #| exercise_start\n",
" #| hint: Use numpy's * operator for element-wise multiplication\n",
" #| solution_test: result should be new Tensor with correct values\n",
" #| difficulty: medium\n",
" \n",
" ### BEGIN SOLUTION\n",
" result_data = self._data * other._data\n",
" return Tensor(result_data)\n",
" ### END SOLUTION\n",
" \n",
" #| exercise_end\n",
" \n",
" def matmul(self, other: 'Tensor') -> 'Tensor':\n",
" \"\"\"\n",
" Matrix multiplication of two tensors.\n",
" \n",
" Args:\n",
" other: Another tensor for matrix multiplication\n",
" \n",
" Returns:\n",
" New tensor with matrix product\n",
" \n",
" Raises:\n",
" ValueError: If shapes are incompatible for matrix multiplication\n",
" \"\"\"\n",
" #| exercise_start\n",
" #| hint: Use np.dot() for matrix multiplication, check shapes first\n",
" #| solution_test: result should handle shape validation and matrix multiplication\n",
" #| difficulty: hard\n",
" \n",
" ### BEGIN SOLUTION\n",
" # Check shape compatibility\n",
" if len(self.shape) != 2 or len(other.shape) != 2:\n",
" raise ValueError(\"Matrix multiplication requires 2D tensors\")\n",
" \n",
" if self.shape[1] != other.shape[0]:\n",
" raise ValueError(f\"Cannot multiply shapes {self.shape} and {other.shape}\")\n",
" \n",
" result_data = np.dot(self._data, other._data)\n",
" return Tensor(result_data)\n",
" ### END SOLUTION\n",
" \n",
" #| exercise_end"
]
},
{
"cell_type": "markdown",
"id": "90c887d9",
"metadata": {
"cell_marker": "\"\"\"",
"lines_to_next_cell": 1
},
"source": [
"## Hidden Tests for Auto-Grading\n",
"\n",
"These tests are hidden from students but used for automatic grading.\n",
"They provide comprehensive coverage and immediate feedback."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "67d0055f",
"metadata": {
"lines_to_next_cell": 1
},
"outputs": [],
"source": [
"### BEGIN HIDDEN TESTS\n",
"def test_tensor_creation_basic():\n",
" \"\"\"Test basic tensor creation (2 points)\"\"\"\n",
" t = Tensor([1, 2, 3])\n",
" assert t.shape == (3,)\n",
" assert t.data.tolist() == [1, 2, 3]\n",
" assert t.size == 3\n",
"\n",
"def test_tensor_creation_scalar():\n",
" \"\"\"Test scalar tensor creation (2 points)\"\"\"\n",
" t = Tensor(5)\n",
" assert t.shape == ()\n",
" assert t.data.item() == 5\n",
" assert t.size == 1\n",
"\n",
"def test_tensor_creation_2d():\n",
" \"\"\"Test 2D tensor creation (2 points)\"\"\"\n",
" t = Tensor([[1, 2], [3, 4]])\n",
" assert t.shape == (2, 2)\n",
" assert t.data.tolist() == [[1, 2], [3, 4]]\n",
" assert t.size == 4\n",
"\n",
"def test_tensor_dtype():\n",
" \"\"\"Test dtype handling (2 points)\"\"\"\n",
" t = Tensor([1, 2, 3], dtype='float32')\n",
" assert t.dtype == np.float32\n",
" assert t.data.dtype == np.float32\n",
"\n",
"def test_tensor_properties():\n",
" \"\"\"Test tensor properties (2 points)\"\"\"\n",
" t = Tensor([[1, 2, 3], [4, 5, 6]])\n",
" assert t.shape == (2, 3)\n",
" assert t.size == 6\n",
" assert isinstance(t.data, np.ndarray)\n",
"\n",
"def test_tensor_repr():\n",
" \"\"\"Test string representation (2 points)\"\"\"\n",
" t = Tensor([1, 2, 3])\n",
" repr_str = repr(t)\n",
" assert \"Tensor\" in repr_str\n",
" assert \"shape\" in repr_str\n",
" assert \"dtype\" in repr_str\n",
"\n",
"def test_tensor_add():\n",
" \"\"\"Test tensor addition (3 points)\"\"\"\n",
" t1 = Tensor([1, 2, 3])\n",
" t2 = Tensor([4, 5, 6])\n",
" result = t1.add(t2)\n",
" assert result.data.tolist() == [5, 7, 9]\n",
" assert result.shape == (3,)\n",
"\n",
"def test_tensor_multiply():\n",
" \"\"\"Test tensor multiplication (3 points)\"\"\"\n",
" t1 = Tensor([1, 2, 3])\n",
" t2 = Tensor([4, 5, 6])\n",
" result = t1.multiply(t2)\n",
" assert result.data.tolist() == [4, 10, 18]\n",
" assert result.shape == (3,)\n",
"\n",
"def test_tensor_matmul():\n",
" \"\"\"Test matrix multiplication (4 points)\"\"\"\n",
" t1 = Tensor([[1, 2], [3, 4]])\n",
" t2 = Tensor([[5, 6], [7, 8]])\n",
" result = t1.matmul(t2)\n",
" expected = [[19, 22], [43, 50]]\n",
" assert result.data.tolist() == expected\n",
" assert result.shape == (2, 2)\n",
"\n",
"def test_tensor_matmul_error():\n",
" \"\"\"Test matrix multiplication error handling (2 points)\"\"\"\n",
" t1 = Tensor([[1, 2, 3]]) # Shape (1, 3)\n",
" t2 = Tensor([[4, 5]]) # Shape (1, 2)\n",
" \n",
" try:\n",
" t1.matmul(t2)\n",
" assert False, \"Should have raised ValueError\"\n",
" except ValueError as e:\n",
" assert \"Cannot multiply shapes\" in str(e)\n",
"\n",
"def test_tensor_immutability():\n",
" \"\"\"Test that operations create new tensors (2 points)\"\"\"\n",
" t1 = Tensor([1, 2, 3])\n",
" t2 = Tensor([4, 5, 6])\n",
" original_data = t1.data.copy()\n",
" \n",
" result = t1.add(t2)\n",
" \n",
" # Original tensor should be unchanged\n",
" assert np.array_equal(t1.data, original_data)\n",
" # Result should be different object\n",
" assert result is not t1\n",
" assert result.data is not t1.data\n",
"\n",
"### END HIDDEN TESTS"
]
},
{
"cell_type": "markdown",
"id": "636ac01d",
"metadata": {
"cell_marker": "\"\"\""
},
"source": [
"## Usage Examples\n",
"\n",
"### Self-Learning Mode\n",
"Students work through the educational content step by step:\n",
"\n",
"```python\n",
"# Create tensors\n",
"t1 = Tensor([1, 2, 3])\n",
"t2 = Tensor([4, 5, 6])\n",
"\n",
"# Basic operations\n",
"result = t1.add(t2)\n",
"print(f\"Addition: {result}\")\n",
"\n",
"# Matrix operations\n",
"matrix1 = Tensor([[1, 2], [3, 4]])\n",
"matrix2 = Tensor([[5, 6], [7, 8]])\n",
"product = matrix1.matmul(matrix2)\n",
"print(f\"Matrix multiplication: {product}\")\n",
"```\n",
"\n",
"### Assignment Mode\n",
"Students submit implementations that are automatically graded:\n",
"\n",
"1. **Immediate feedback**: Know if implementation is correct\n",
"2. **Partial credit**: Earn points for each working method\n",
"3. **Hidden tests**: Comprehensive coverage beyond visible examples\n",
"4. **Error handling**: Points for proper edge case handling\n",
"\n",
"### Benefits of Dual System\n",
"\n",
"1. **Single source**: One implementation serves both purposes\n",
"2. **Consistent quality**: Same instructor solutions everywhere\n",
"3. **Flexible assessment**: Choose the right tool for each situation\n",
"4. **Scalable**: Handle large courses with automated feedback\n",
"\n",
"This approach transforms TinyTorch from a learning framework into a complete course management solution."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cd296b25",
"metadata": {},
"outputs": [],
"source": [
"# Test the implementation\n",
"if __name__ == \"__main__\":\n",
" # Basic testing\n",
" t1 = Tensor([1, 2, 3])\n",
" t2 = Tensor([4, 5, 6])\n",
" \n",
" print(f\"t1: {t1}\")\n",
" print(f\"t2: {t2}\")\n",
" print(f\"t1 + t2: {t1.add(t2)}\")\n",
" print(f\"t1 * t2: {t1.multiply(t2)}\")\n",
" \n",
" # Matrix multiplication\n",
" m1 = Tensor([[1, 2], [3, 4]])\n",
" m2 = Tensor([[5, 6], [7, 8]])\n",
" print(f\"Matrix multiplication: {m1.matmul(m2)}\")\n",
" \n",
" print(\"✅ Enhanced tensor module working!\") "
]
}
],
"metadata": {
"jupytext": {
"main_language": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}