إنتقل إلى المحتوى الرئيسي

تعلم الآلة في Cursor: TensorFlow.js و ONNX وخطوط أنابيب ML بمساعدة الذكاء الاصطناعي

تعلم الآلة في Cursor

يجلب تعلم الآلة ذكاءً تنبؤيًا إلى التطبيقات، من تصنيف الصور إلى معالجة اللغة الطبيعية وأنظمة التوصية. Cursor، وهو محرر IDE مدعوم بالذكاء الاصطناعي، يسرّع كل مرحلة من مراحل سير عمل ML: معالجة البيانات المسبقة، وتصميم النموذج، وحلقات التدريب، ومقاييس التقييم، والنشر. يغطي هذا الدليل TensorFlow.js للاستنتاج والتدريب في المتصفح، و ONNX Runtime لتنفيذ النماذج متعدد المنصات، وخطوط أنابيب معالجة البيانات المسبقة، واستراتيجيات تقييم النماذج، وتوليد خطوط أنابيب ML بمساعدة الذكاء الاصطناعي الذي يحول الأوصاف باللغة الطبيعية إلى نصوص برمجة تدريب تعمل.

المتطلبات الأساسية​

قبل البدء، تأكد من أن لديك ما يلي:

  • Cursor (يُوصى بأحدث إصدار) كمحرر IDE الخاص بك
  • Node.js 18 أو أحدث
  • معرفة أساسية بـ JavaScript و TypeScript و Python
  • فهم مفاهيمي للشبكات العصبية ودوال الخسارة والانحدار التدرجي
تلميح

إذا كنت جديدًا على تعلم الآلة، اطلب من Cursor شرح الفرق بين التعلم الخاضع للإشراف وغير الخاضع للإشراف والتعلم المعزز قبل كتابة أي كود. فهم أي نموذج يقع ضمنه مشكلتك يحدد نهجك بالكامل: وسم البيانات، وعمارة النموذج، ومقاييس التقييم.

فهم سير عمل ML في Cursor​

يتبع مشروع تعلم الآلة النموذجي خط أنابيب يمكن التنبؤ به. يساعدك Cursor في تنفيذ وربط كل مرحلة:

  1. جمع البيانات والمعالجة المسبقة: تنظيف البيانات الخام، والتعامل مع القيم المفقودة، وتطبيع الميزات، والتقسيم إلى مجموعات تدريب/تحقق/اختبار.
  2. تصميم النموذج: اختيار عمارة (شبكة كثيفة، CNN، RNN، محول) وتعريف الطبقات.
  3. التدريب: تشغيل حلقة التدريب مع محسن ودالة خسارة محددين، ومراقبة المقاييس، وتطبيق الإيقاف المبكر.
  4. التقييم: قياس الأداء بالدقة والاستدعاء و F1-score ومصفوفات الالتباس ومقاييس أخرى.
  5. النشر: تصدير النموذج، وتحويله إلى ONNX إذا لزم، وتشغيل الاستنتاج في المتصفح أو على خادم.

إنشاء هيكل المشروع​

اطلب من Cursor إنشاء مشروع TensorFlow.js:

Create a TypeScript project for machine learning with TensorFlow.js.
Set up Vite for the frontend, install @tensorflow/tfjs and
@tensorflow/tfjs-node, and create a folder structure for data,
models, training scripts, and evaluation utilities.

يقوم Cursor بتوليد:

my-ml-project/
data/
raw/
processed/
models/
src/
train.ts
evaluate.ts
predict.ts
src-tauri/ (optional, for desktop deployment)
package.json
tsconfig.json
warning

استخدم دائمًا @tensorflow/tfjs-node (الذي يرتبط بمكتبة TensorFlow الأصلية بـ C++) للتدريب، وليس @tensorflow/tfjs النقي (الذي يعمل على WebGL/WASM في المتصفح). التدريب على Node.js أسرع 10 إلى 50 مرة من التدريب في المتصفح لأنه يستفيد من تعليمات SIMD وإدارة الذاكرة الأصلية. TensorFlow.js للمتصفح للاستنتاج، وليس للتدريب الثقيل.

معالجة البيانات المسبقة​

تستهلك المعالجة المسبقة للبيانات معظم وقت تطوير ML. يمكن لـ Cursor توليد خطوط أنابيب معالجة مسبقة كاملة تتعامل مع التنظيف والتطبيع والترميز والتقسيم.

خط أنابيب المعالجة المسبقة​

// src/preprocessing.ts
import * as tf from '@tensorflow/tfjs-node';

export interface DatasetStats {
mean: number[];
std: number[];
min: number[];
max: number[];
}

export class DataPreprocessor {
private stats: DatasetStats | null = null;

/**
* Compute normalization statistics from training data.
* Must be called before normalize() and applied identically
* to training, validation, and test sets.
*/
computeStats(data: number[][]): void {
const tensor = tf.tensor2d(data);
const mean = tensor.mean(0).dataSync();
const std = tensor.sub(tensor.mean(0)).square().mean(0).sqrt().dataSync();
const min = tensor.min(0).dataSync();
const max = tensor.max(0).dataSync();

this.stats = {
mean: Array.from(mean),
std: Array.from(std).map((s, i) => (s < 1e-8 ? 1 : s)), // Avoid division by zero
min: Array.from(min),
max: Array.from(max),
};

tensor.dispose();
}

/**
* Apply Z-score normalization: (x - mean) / std
*/
normalize(data: number[][]): number[][] {
if (!this.stats) throw new Error('Call computeStats() first');
return data.map((row) =>
row.map((val, i) => (val - this.stats!.mean[i]) / this.stats!.std[i])
);
}

/**
* One-hot encode categorical labels
*/
encodeLabels(labels: number[], numClasses: number): number[][] {
return labels.map((label) => {
const encoded = new Array(numClasses).fill(0);
encoded[label] = 1;
return encoded;
});
}

/**
* Split data into train, validation, and test sets
*/
split(
data: number[][],
labels: number[][],
trainRatio = 0.7,
valRatio = 0.15
): { trainX: number[][]; trainY: number[]; valX: number[][]; valY: number[]; testX: number[][]; testY: number[] } {
const n = data.length;
const indices = Array.from({ length: n }, (_, i) => i);
// Fisher-Yates shuffle
for (let i = n - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[indices[i], indices[j]] = [indices[j], indices[i]];
}
const trainEnd = Math.floor(n * trainRatio);
const valEnd = trainEnd + Math.floor(n * valRatio);
const pick = (idx: number[]) => ({ x: idx.map((i) => data[i]), y: idx.map((i) => labels[i]) });
const train = pick(indices.slice(0, trainEnd));
const val = pick(indices.slice(trainEnd, valEnd));
const test = pick(indices.slice(valEnd));
return { trainX: train.x, trainY: train.y, valX: val.x, valY: val.y, testX: test.x, testY: test.y };
}

/**
* Handle missing values by imputing the column mean
*/
imputeMissing(data: (number | null)[][]): number[][] {
const numCols = data[0].length;
const colSums = new Array(numCols).fill(0);
const colCounts = new Array(numCols).fill(0);

data.forEach((row) => {
row.forEach((val, col) => {
if (val !== null && !isNaN(val)) { colSums[col] += val; colCounts[col]++; }
});
});

const colMeans = colSums.map((sum, i) => (colCounts[i] > 0 ? sum / colCounts[i] : 0));

return data.map((row) => row.map((val, col) => (val === null || isNaN(val) ? colMeans[col] : val)));
}

getStats(): DatasetStats | null {
return this.stats;
}
}
تلميح

اطلب من Cursor توليد مجموعات بيانات اصطناعية لاختبار خط أنابيب المعالجة المسبقة الخاص بك. أمر مثل "Generate a synthetic CSV with 1000 rows, 8 numeric features, 2 categorical columns, and 5% missing values" يمنحك بيانات اختبار واقعية دون الحاجة للعثور على وتنزيل مجموعة بيانات حقيقية أولاً.

تصميم النموذج والتدريب​

يستخدم TensorFlow.js واجهة برمجية طبقية لبناء الشبكات العصبية. يقوم Cursor بتوليد عمارات نماذج كاملة بناءً على وصف مشكلتك.

بناء نموذج تصنيف​

// src/models/classifier.ts
import * as tf from '@tensorflow/tfjs-node';

export interface ModelConfig {
inputSize: number;
numClasses: number;
hiddenLayers: number[];
learningRate: number;
dropoutRate: number;
}

export function buildClassifier(config: ModelConfig): tf.LayersModel {
const model = tf.sequential();

// Input layer
model.add(
tf.layers.dense({
inputShape: [config.inputSize],
units: config.hiddenLayers[0],
activation: 'relu',
kernelInitializer: 'heNormal',
})
);

model.add(tf.layers.batchNormalization());
model.add(tf.layers.dropout({ rate: config.dropoutRate }));

// Hidden layers
for (let i = 1; i < config.hiddenLayers.length; i++) {
model.add(
tf.layers.dense({
units: config.hiddenLayers[i],
activation: 'relu',
kernelInitializer: 'heNormal',
})
);
model.add(tf.layers.batchNormalization());
model.add(tf.layers.dropout({ rate: config.dropoutRate }));
}

// Output layer
model.add(
tf.layers.dense({
units: config.numClasses,
activation: 'softmax',
})
);

model.compile({
optimizer: tf.train.adam(config.learningRate),
loss: 'categoricalCrossentropy',
metrics: ['accuracy'],
});

return model;
}

حلقة التدريب مع الاستدعاءات​

// src/train.ts
import * as tf from '@tensorflow/tfjs-node';
import { buildClassifier, ModelConfig } from './models/classifier';
import { DataPreprocessor } from './preprocessing';
import * as fs from 'fs/promises';
import * as path from 'path';

interface TrainingResult {
finalAccuracy: number;
finalLoss: number;
epochsRun: number;
modelPath: string;
}

export async function trainModel(
dataPath: string,
config: ModelConfig,
outputDir: string
): Promise<TrainingResult> {
// Load and preprocess data
const rawData = await loadCSV(dataPath);
const features = rawData.map((row) => row.slice(0, config.inputSize));
const labels = rawData.map((row) => row[config.inputSize]);

const preprocessor = new DataPreprocessor();
preprocessor.computeStats(features);
const normalizedFeatures = preprocessor.normalize(features);

const encodedLabels = preprocessor.encodeLabels(labels, config.numClasses);

const split = preprocessor.split(normalizedFeatures, labels);

const trainXTensor = tf.tensor2d(split.trainX);
const trainYTensor = tf.tensor2d(
preprocessor.encodeLabels(split.trainY, config.numClasses)
);
const valXTensor = tf.tensor2d(split.valX);
const valYTensor = tf.tensor2d(
preprocessor.encodeLabels(split.valY, config.numClasses)
);

// Build model
const model = buildClassifier(config);

// Train with callbacks
const history = await model.fit(trainXTensor, trainYTensor, {
epochs: 100,
batchSize: 32,
validationData: [valXTensor, valYTensor],
shuffle: true,
callbacks: [
tf.callbacks.earlyStopping({ monitor: 'val_loss', patience: 10, minDelta: 0.001, restoreBestWeight: true }),
{
onEpochEnd: async (epoch, logs) => {
if (epoch > 0 && epoch % 20 === 0) {
console.log(`Epoch ${epoch}: Consider reducing learning rate`);
}
console.log(`Epoch ${epoch + 1}: loss=${logs?.loss?.toFixed(4)}, acc=${logs?.acc?.toFixed(4)}, val_loss=${logs?.val_loss?.toFixed(4)}, val_acc=${logs?.val_acc?.toFixed(4)}`);
},
},
],
});

// Save model and preprocessor stats
const modelPath = path.join(outputDir, 'model');
await model.save(`file://${modelPath}`);
await fs.writeFile(path.join(outputDir, 'preprocessor-stats.json'), JSON.stringify(preprocessor.getStats(), null, 2));

// Cleanup tensors
[trainXTensor, trainYTensor, valXTensor, valYTensor].forEach((t) => t.dispose());

const lastEpoch = history.epoch.length;
const finalAccuracy = history.history.val_acc?.[lastEpoch - 1] ?? 0;
const finalLoss = history.history.val_loss?.[lastEpoch - 1] ?? 0;

console.log(`\nTraining complete after ${lastEpoch} epochs`);
console.log(`Best validation accuracy: ${finalAccuracy.toFixed(4)}`);
console.log(`Model saved to: ${modelPath}`);

return { finalAccuracy, finalLoss, epochsRun: lastEpoch, modelPath };
}

async function loadCSV(filePath: string): Promise<number[][]> {
const lines = (await fs.readFile(filePath, 'utf-8')).trim().split('\n');
const header = lines[0].split(',').length;
return lines.slice(1)
.map((line) => line.split(',').map((v) => parseFloat(v.trim())))
.filter((row) => row.length === header && row.every((v) => !isNaN(v)));
}
تلميح

عندما يستغرق التدريب وقتًا طويلاً، اطلب من Cursor تحليل اختناق الأداء. أمر مثل "Analyze my training script for performance issues. Check for tensor memory leaks, unnecessary synchronous operations, and data loading bottlenecks" يحدد مشكلات مثل الموترات غير المرنة التي تسبب ضغط الذاكرة والتباطؤ.

warning

موترات TensorFlow.js لا يتم جمعها كقمامة. كل موتر تنشئه يبقى في الذاكرة حتى تستدعي .dispose() أو تغلفه في tf.tidy(). في حلقة تدريب، إنشاء الموترات دون تصريف يؤدي إلى نمو الذاكرة حتى ينهار العملية. تخلص دائمًا من الموترات بعد الاستخدام واستخدم tf.tidy() للحسابات قصيرة العمر.

تقييم النموذج​

التقييم يتجاوز الدقة. يقوم Cursor بتوليد كود تقييم شامل يحسب مقاييس متعددة ويصور النتائج.

مقاييس التقييم​

// src/evaluate.ts
import * as tf from '@tensorflow/tfjs-node';
import { DataPreprocessor } from './preprocessing';

export interface EvaluationResult {
accuracy: number;
precision: number;
recall: number;
f1Score: number;
confusionMatrix: number[][];
perClassMetrics: Array<{
class: number;
precision: number;
recall: number;
f1: number;
support: number;
}>;
}

export async function evaluateModel(
model: tf.LayersModel,
testX: number[][],
testY: number[],
numClasses: number,
preprocessor: DataPreprocessor
): Promise<EvaluationResult> {
const inputTensor = tf.tensor2d(preprocessor.normalize(testX));
const predictions = model.predict(inputTensor) as tf.Tensor;
const predicted = predictions.argMax(1).dataSync();
const actual = tf.tensor1d(testY).dataSync();

// Build confusion matrix
const confusionMatrix: number[][] = Array.from({ length: numClasses }, () => new Array(numClasses).fill(0));
for (let i = 0; i < predicted.length; i++) confusionMatrix[actual[i]][predicted[i]]++;

// Per-class metrics
const perClassMetrics: EvaluationResult['perClassMetrics'] = [];
let totalCorrect = 0;
let totalSamples = 0;

for (let c = 0; c < numClasses; c++) {
const tp = confusionMatrix[c][c];
const fp = confusionMatrix.reduce((sum, row, idx) => sum + (idx !== c ? row[c] : 0), 0);
const fn = confusionMatrix[c].reduce((sum, val, idx) => sum + (idx !== c ? val : 0), 0);
const support = confusionMatrix[c].reduce((a, b) => a + b, 0);

const precision = tp + fp > 0 ? tp / (tp + fp) : 0;
const recall = tp + fn > 0 ? tp / (tp + fn) : 0;
const f1 = precision + recall > 0 ? (2 * precision * recall) / (precision + recall) : 0;

perClassMetrics.push({ class: c, precision, recall, f1, support });
totalCorrect += tp;
totalSamples += support;
}

// Macro-averaged metrics
const macroPrecision = perClassMetrics.reduce((sum, m) => sum + m.precision, 0) / numClasses;
const macroRecall = perClassMetrics.reduce((sum, m) => sum + m.recall, 0) / numClasses;
const macroF1 = perClassMetrics.reduce((sum, m) => sum + m.f1, 0) / numClasses;

inputTensor.dispose();
predictions.dispose();

return {
accuracy: totalCorrect / totalSamples,
precision: macroPrecision,
recall: macroRecall,
f1Score: macroF1,
confusionMatrix,
perClassMetrics,
};
}

export function printEvaluation(result: EvaluationResult): void {
console.log('\n=== Model Evaluation ===\n');
console.log(`Accuracy: ${(result.accuracy * 100).toFixed(2)}%`);
console.log(`Precision: ${(result.precision * 100).toFixed(2)}%`);
console.log(`Recall: ${(result.recall * 100).toFixed(2)}%`);
console.log(`F1-Score: ${(result.f1Score * 100).toFixed(2)}%`);

console.log('\nPer-Class Metrics:');
console.log('Class | Precision | Recall | F1 | Support');
result.perClassMetrics.forEach((m) => {
console.log(` ${m.class} | ${(m.precision * 100).toFixed(1)}% | ${(m.recall * 100).toFixed(1)}% | ${(m.f1 * 100).toFixed(1)}% | ${m.support}`);
});

console.log('\nConfusion Matrix:');
result.confusionMatrix.forEach((row, i) => {
console.log(` ${i}: ` + row.join(' '));
});
}
تلميح

اطلب من Cursor توليد أداة تصور مصفوفة الالتباس نصية وأيضًا تقرير HTML. أمر مثل "Create an HTML template that renders the evaluation results as a styled report with a confusion matrix heatmap, per-class metric bars, and a summary table" يمنحك تقارير تقييم قابلة للمشاركة لأصحاب المصلحة.

ONNX Runtime للاستنتاج متعدد المنصات​

ONNX (Open Neural Network Exchange) هو تنسيق قياسي لتمثيل نماذج ML يعمل على العديد من المنصات. حوّل نموذج TensorFlow.js إلى ONNX وشغل الاستنتاج في المتصفح أو على الجوال أو على أجهزة الحافة.

التحويل إلى ONNX​

# scripts/convert_to_onnx.py
# Run this script to convert a saved TF model to ONNX format
import tensorflow as tf
import tf2onnx
import onnxruntime as ort
import numpy as np

# Load the saved TensorFlow model
model = tf.keras.models.load_model('models/saved_model')

# Convert to ONNX
spec = (tf.TensorSpec((None, 8), tf.float32, name='input'),)
onnx_model, _ = tf2onnx.convert.from_keras(model, input_signature=spec, opset=15)

# Save the ONNX model
with open('models/model.onnx', 'wb') as f:
f.write(onnx_model.SerializeToString())

# Verify with ONNX Runtime
session = ort.InferenceSession('models/model.onnx')
print(f"ONNX model inputs: {session.get_inputs()[0].name}")
print(f"ONNX model outputs: {[o.name for o in session.get_outputs()]}")

# Quick sanity check with dummy data
dummy_input = np.random.randn(1, 8).astype(np.float32)
result = session.run(None, {'input': dummy_input})
print(f"Test inference output shape: {result[0].shape}")

تشغيل استنتاج ONNX في المتصفح​

// src/predict.ts
import * as ort from 'onnxruntime-web';

export interface PredictionResult {
predictedClass: number;
confidence: number;
probabilities: number[];
}

export class OnnxPredictor {
private session: ort.InferenceSession | null = null;
private inputName: string = '';
private outputName: string = '';

async loadModel(modelPath: string): Promise<void> {
this.session = await ort.InferenceSession.create(modelPath, {
executionProviders: ['wasm'],
graphOptimizationLevel: 'all',
});

this.inputName = this.session.inputNames[0];
this.outputName = this.session.outputNames[0];
}

async predict(features: number[], mean: number[], std: number[]): Promise<PredictionResult> {
if (!this.session) throw new Error('Model not loaded. Call loadModel() first.');

// Normalize input
const normalized = features.map((val, i) => (val - mean[i]) / std[i]);

// Create ONNX tensor
const input = new ort.Tensor('float32', Float32Array.from(normalized), [1, normalized.length]);

// Run inference
const outputs = await this.session.run({ [this.inputName]: input });
const output = outputs[this.outputName];

// Convert to probabilities
const probabilities = Array.from(output.data as Float32Array);
const maxIndex = probabilities.indexOf(Math.max(...probabilities));

return {
predictedClass: maxIndex,
confidence: probabilities[maxIndex],
probabilities,
};
}
}
تلميح

عند تحميل نماذج ONNX في المتصفح، استخدم onnxruntime-web مع مزود تنفيذ wasm. مزود webgl أسرع لكن لديه مشكلات توافق مع بعض عمارات النماذج. اطلب من Cursor قياس أداء كلا المزودين على نموذجك المحدد وتوصية الأفضل.

warning

يمكن أن تكون ملفات نماذج ONNX كبيرة (10MB إلى 500MB). تحميلها في المتصفح يوقف خيط واجهة المستخدم. استخدم دائمًا Web Worker لاستنتاج ONNX للحفاظ على استجابة تطبيقك. اطلب من Cursor تغليف المتنبئ في Worker مع واجهة تمرير رسائل.

توليد خط أنابيب ML بمساعدة الذكاء الاصطناعي​

أقوى ميزة ML في Cursor هي توليد خطوط أنابيب تدريب كاملة من وصف باللغة الطبيعية. صف مشكلتك، وينتج Cursor كود البرمجة الكامل.

توليد خط أنابيب كامل​

Create a complete machine learning pipeline for customer churn prediction:
1. Load a CSV with columns: tenure, monthlyCharges, totalCharges, contractType, internetService, churn
2. Handle missing values in totalCharges (impute median)
3. One-hot encode contractType and internetService
4. Normalize all numeric features with Z-score
5. Split 70/15/15 train/val/test
6. Build a dense neural network with 3 hidden layers (64, 32, 16) and dropout
7. Train with Adam optimizer, binary crossentropy loss, early stopping
8. Evaluate with accuracy, precision, recall, F1, and confusion matrix
9. Save the model and preprocessor stats
10. Export to ONNX format

Write all code in TypeScript using @tensorflow/tfjs-node.

يقوم Cursor بتوليد خط الأنابيب الكامل في ملفات متعددة، متصلة وجاهزة للتشغيل. هذا يعادل كتابة 500+ سطر من الكود النمطي يدويًا.

تلميح

كرّر على خط الأنابيب الخاص بك بطلب Cursor تعديل أجزاء محددة. على سبيل المثال: "Change the model architecture to use BatchNorm before each Dense layer" أو "Add class weight balancing because the churn class is only 20% of the data." هذا النهج التزايدي يتيح لك التجربة بسرعة دون إعادة كتابة خط الأنابيب بالكامل.

أنماط نشر النموذج​

يمكن أن تكون ملفات نماذج ONNX كبيرة (10MB إلى 500MB). تحميلها في المتصفح يوقف خيط واجهة المستخدم. استخدم دائمًا Web Worker للاستنتاج للحفاظ على استجابة التطبيق.

الاستنتاج في المتصفح مع Web Worker​

// src/worker/inference-worker.ts
import { OnnxPredictor } from '../lib/predict';

let predictor: OnnxPredictor | null = null;

self.onmessage = async (event: MessageEvent) => {
const { type, modelPath, features, stats } = event.data;
if (type === 'load' && modelPath) {
predictor = new OnnxPredictor();
await predictor.loadModel(modelPath);
self.postMessage({ type: 'loaded' });
} else if (type === 'predict' && features && stats && predictor) {
const result = await predictor.predict(features, stats.mean, stats.std);
self.postMessage({ type: 'result', result });
}
};

استخدام Worker في الخيط الرئيسي​

// src/lib/inference-client.ts
import { PredictionResult } from './predict';

export class InferenceClient {
private worker = new Worker(new URL('../worker/inference-worker.ts', import.meta.url));

async loadModel(modelPath: string): Promise<void> {
return new Promise((resolve) => {
const handler = () => { this.worker.removeEventListener('message', handler); resolve(); };
this.worker.addEventListener('message', handler);
this.worker.postMessage({ type: 'load', modelPath });
});
}

async predict(features: number[], stats: { mean: number[]; std: number[] }): Promise<PredictionResult> {
return new Promise((resolve) => {
const handler = (event: MessageEvent) => {
if (event.data.type === 'result') {
this.worker.removeEventListener('message', handler);
resolve(event.data.result);
}
};
this.worker.addEventListener('message', handler);
this.worker.postMessage({ type: 'predict', features, stats });
});
}
}
تلميح

اطلب من Cursor توليد مكون React كامل يحمل نموذج ONNX في Worker، ويقبل إدخال المستخدم من خلال نموذج، ويشغل الاستنتاج، ويعرض التنبؤ مع شريط ثقة. هذا النمط الشامل يوضح سير عمل النشر الكامل من ملف النموذج إلى واجهة المستخدم.

الخلاصة​

يجلب تعلم الآلة في Cursor دورة حياة ML الكاملة إلى محرر IDE واحد مدعوم بالذكاء الاصطناعي. باتباع أنماط هذا الدليل، معالجة البيانات المسبقة المنظمة، ونماذج TensorFlow.js ذات العمارة الجيدة، ومقاييس التقييم الشاملة، ونشر ONNX متعدد المنصات، وتوليد خطوط الأنابيب بمساعدة الذكاء الاصطناعي، يمكنك أخذ مشروع تعلم آلة من الفكرة إلى الإنتاج أسرع من أي وقت مضى. تذكر إدارة ذاكرة الموتر بعناية، والتقييم دائمًا بمقاييس متعددة تتجاوز الدقة، ودع Cursor يولد الكود النمطي الخاص بك بحيث يمكنك التركيز على عمارة النموذج وجودة البيانات.