אתה מאמן מודל סיווג תמונות על PyTorch—דיוק של 95%, אבל איך מריצים אותו על iOS ללא חביון וללא שליחת נתונים לענן? Core ML עם עיבוד על-המכשיר פותר את זה. אנו משלבים מודלים של Core ML באפליקציות iOS ל-AI אופליין מלא. מהירות עיבוד—יחידות אלפיות שנייה בודדות, הנתונים נשארים על המכשיר, אין חביון רשת. הצוות שלנו—7 שנות ניסיון בפיתוח מובייל, מעל 50 אינטגרציות מוצלחות של Core ML. חיסכון בעלויות שרת יכול להגיע ל-60% (מעל $1.8k–2.6k לשנה לפרויקט ממוצע). אנו מבטיחים איכות אינטגרציה, המאושרת על ידי הסמכות Apple Developer.
איך ההמרה עובדת: ממשקלים ל-.mlpackage
רוב המודלים המודרניים מגיעים כקבצי PyTorch checkpoints או קבצי ONNX. אנו ממירים באמצעות coremltools—החבילה הרשמית של Apple ב-Python:
import coremltools as ct
import torch
# Допустим, у нас PyTorch модель классификации изображений
model = MyModel()
model.load_state_dict(torch.load("model.pth"))
model.eval()
# Tracing — нужно передать пример входных данных
example_input = torch.zeros(1, 3, 224, 224)
traced = torch.jit.trace(model, example_input)
# Конвертация
mlmodel = ct.convert(
traced,
inputs=[ct.ImageType(
name="input_image",
shape=(1, 3, 224, 224),
color_layout=ct.colorlayout.RGB,
bias=[-0.485/0.229, -0.456/0.224, -0.406/0.225], # ImageNet нормализация
scale=1/(255.0 * 0.229) # встроена в модель, не нужно делать в Swift
)],
outputs=[ct.TensorType(name="class_probabilities")],
compute_precision=ct.precision.FLOAT16, # для ANE
minimum_deployment_target=ct.target.iOS16
)
mlmodel.save("MyClassifier.mlpackage")import coremltools as ct import torch # Допустим, у нас PyTorch модель классификации изображений model = MyModel() model.load_state_dict(torch.load("model.pth")) model.eval() # Tracing — нужно передать пример входных данных example_input = torch.zeros(1, 3, 224, 224) traced = torch.jit.trace(model, example_input) # Конвертация mlmodel = ct.convert( traced, inputs=[ct.ImageType( name="input_image", shape=(1, 3, 224, 224), color_layout=ct.colorlayout.RGB, bias=[-0.485/0.229, -0.456/0.224, -0.406/0.225], # ImageNet нормализация scale=1/(255.0 * 0.229) # встроена в модель, не нужно делать в Swift )], outputs=[ct.TensorType(name="class_probabilities")], compute_precision=ct.precision.FLOAT16, # для ANE minimum_deployment_target=ct.target.iOS16 ) mlmodel.save("MyClassifier.mlpackage") + torch.Size([batch, seq_len, hidden]) מפעיל את Apple Neural Engine. באייפון 14, זה מהיר פי 4–8 מ-GPU לעיבוד, עם צריכת סוללה נמוכה משמעותית. לפי התיעוד של Apple ל-Core ML, ANE מאיץ עיבוד פי 4–8 בהשוואה ל-GPU. בגרסאות iOS ישנות יותר, אותו מודל רץ דרך Metal GPU.
איך ממירים מודל מ-PyTorch ל-Core ML?
צורות דינמיות—מודלים עם seq_len כאשר torch.jit.trace אינו קבוע שוברים את ct.RangeDim. פתרון: ct.EnumeratedShapes לגדלים משתנים או הגדרת מספר תצורות דרך # Переменная длина последовательности flexible_shape = ct.Shape(shape=(1, ct.RangeDim(1, 512), 768)) mlmodel = ct.convert(model, inputs=[ct.TensorType(shape=flexible_shape)]) .
# Переменная длина последовательности
flexible_shape = ct.Shape(shape=(1, ct.RangeDim(1, 512), 768))
mlmodel = ct.convert(model, inputs=[ct.TensorType(shape=flexible_shape)])פעולות לא נתמכות—לדוגמה, ליבות CUDA מותאמות אישית. coremltools זורק NotImplementedError. נתיב: או לשכתב את הפעולה באמצעות פרימיטיבים סטנדרטיים של PyTorch, או להוסיף שכבה מותאמת אישית דרך הרחבת C++/Swift.
שגיאה Unsupported model format בעת טעינת .mlpackage בסימולטור x86—הסימולטור משתמש ב-CPU fallback, חלק מפעולות FLOAT16 אינן נתמכות. בדוק דיוק רק על מכשיר אמיתי.
טעינה והרצה על iOS
import CoreML
import Vision
// Загрузка модели (один раз при старте)
let config = MLModelConfiguration()
config.computeUnits = .all // ANE + GPU + CPU
// .mlpackage загружается из bundle
guard let modelURL = Bundle.main.url(forResource: "MyClassifier", withExtension: "mlpackage"),
let model = try? MyClassifier(contentsOf: modelURL, configuration: config) else {
fatalError("Не удалось загрузить модель")
}
// Инференс — в фоновом потоке
DispatchQueue.global(qos: .userInitiated).async {
do {
let input = MyClassifierInput(input_image: cgImage)
let output = try model.prediction(input: input)
let probs = output.class_probabilities
// probs — MLMultiArray, достать значение:
probs[0].doubleValue
} catch {
print("Ошибка инференса: \(error)")
}
}טעינת המודל אורכת ~100–300 אלפיות שנייה (תלוי בגודל). אל תטען אותו ב-import CoreML import Vision // Загрузка модели (один раз при старте) let config = MLModelConfiguration() config.computeUnits = .all // ANE + GPU + CPU // .mlpackage загружается из bundle guard let modelURL = Bundle.main.url(forResource: "MyClassifier", withExtension: "mlpackage"), let model = try? MyClassifier(contentsOf: modelURL, configuration: config) else { fatalError("Не удалось загрузить модель") } // Инференс — в фоновом потоке DispatchQueue.global(qos: .userInitiated).async { do { let input = MyClassifierInput(input_image: cgImage) let output = try model.prediction(input: input) let probs = output.class_probabilities // probs — MLMultiArray, достать значение: probs[0].doubleValue } catch { print("Ошибка инференса: \(error)") } } —טען פעם אחת בעת השקת האפליקציה או בשימוש ראשון, ושמור בזיכרון כל עוד יש צורך.
למה ML על-המכשיר מהיר ובטוח יותר מענן?
ML על-המכשיר מבטל חביון רשת, שומר על פרטיות נתוני המשתמש, ועובד אופליין. אתה לא משלם על עיבוד שרת ולא תלוי בחיבור אינטרנט. למשימות שבהן מהירות תגובה קריטית (למשל, עיבוד וידאו בזמן אמת), המכשיר הוא האפשרות ההגיונית היחידה.
| קריטריון | Core ML | AI בענן |
|---|---|---|
| חביון | <10 אלפיות שנייה | 100–500 אלפיות שנייה |
| פרטיות | נתונים על המכשיר | נשלחים לשרת |
| אופליין | כן | לא |
| עלות | אין עלות עיבוד | תשלום לכל קריאת API |
ביצועים על מכשירים אמיתיים:
| מכשיר | מודל | computeUnits | זמן עיבוד |
|---|---|---|---|
| iPhone 14 Pro | MobileNetV3 (5 MB FP16) | .all (ANE) | 2–4 אלפיות שנייה |
| iPhone 14 Pro | ResNet-50 (48 MB FP16) | .all (ANE) | 8–15 אלפיות שנייה |
| iPhone 12 | BERT-base (350 MB FP16) | .all | 180–250 אלפיות שנייה |
| iPhone SE דור 2 | MobileNetV3 (5 MB FP16) | .cpuOnly | 12–20 אלפיות שנייה |
לפרופילינג, השתמש ב-Xcode Instruments → Core ML Instrument.
Vision Framework כעטיפה
למשימות ראייה ממוחשבת, viewDidLoad נוח יותר—Vision מטפל בשינוי גודל קלט, כיוון תמונה, וטרנספורמציות קואורדינטות:
let coreMLModel = try VNCoreMLModel(for: model.model) // .model — MLModel из generated class
let request = VNCoreMLRequest(model: coreMLModel) { request, error in
guard let results = request.results as? [VNClassificationObservation] else { return }
let topResult = results.sorted { $0.confidence > $1.confidence }.first
print("\(topResult?.identifier ?? "?") — \(topResult?.confidence ?? 0)")
}
request.imageCropAndScaleOption = .centerCrop // или .scaleFit
let handler = VNImageRequestHandler(cgImage: inputCGImage, options: [:])
try handler.perform([request])VNCoreMLRequest פותר אוטומטית את בעיית אי-התאמת גודל הקלט—אתה מעביר תמונה שרירותית, ו-Vision משנה את גודלה לגודל המצופה של המודל. ללא Vision, היית צריך לעשות זאת ידנית דרך let coreMLModel = try VNCoreMLModel(for: model.model) // .model — MLModel из generated class let request = VNCoreMLRequest(model: coreMLModel) { request, error in guard let results = request.results as? [VNClassificationObservation] else { return } let topResult = results.sorted { $0.confidence > $1.confidence }.first print("\(topResult?.identifier ?? "?") — \(topResult?.confidence ?? 0)") } request.imageCropAndScaleOption = .centerCrop // или .scaleFit let handler = VNImageRequestHandler(cgImage: inputCGImage, options: [:]) try handler.perform([request]) או VNCoreMLRequest.
מה כלול בעבודה
- תיעוד על המרה ואינטגרציה, כולל תיאור כל השלבים והכלים בהם נעשה שימוש.
- גישה למאגר עם קוד מקור להמרה ודוגמאות אינטגרציה.
- הכשרת צוות הלקוח לעבודה עם Core ML, פרופילינג ועדכוני מודלים.
- תמיכה לחודש אחד לאחר האינטגרציה לפתרון כל בעיה.
איך לעדכן מודל ללא עדכון האפליקציה?
Core ML תומך בטעינת מודל מ-vImage שרירותי, לא רק מה-bundle. זה מאפשר עדכון מודל דרך השרת:
// Загружаем mlpackage из документов-директории
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let downloadedModelURL = documentsURL.appendingPathComponent("updated_model.mlpackage")
if FileManager.default.fileExists(atPath: downloadedModelURL.path) {
let model = try MyClassifier(contentsOf: downloadedModelURL, configuration: config)
} else {
// Fallback на bundle
}הורד מודל דרך הרשת באמצעות CIImage, שמור ב-Documents, ובדוק באמצעות גיבוב SHA-256 לפני השימוש.
הגישה שלנו: מניתוח ועד פריסה
- ניתוח המודל המקורי (מסגרת, משקלים, מבנה).
- המרה ל-Core ML עם אופטימיזציה של דיוק ויחידות עיבוד.
- אופטימיזציה למכשירי יעד (פרופילינג על מכשירים אמיתיים).
- אינטגרציה לאפליקציה: טעינה, שמירה במטמון, fallback בשגיאות.
- הגדרת עדכון מודל מרחוק (אופציונלי).
- תיעוד והכשרת צוות.
שלבי התהליך:
- אנליטיקה—קבלת משקלים, הערכת מורכבות, בחירת אסטרטגיית המרה.
- המרה—יצירת .mlpackage, פתרון בעיות פעולות ומימדים.
- פרופילינג—מדידת מהירות וצריכת אנרגיה על מספר דורות של iPhone.
- אינטגרציה—שילוב ב-SwiftUI/UIKit, הוספת טיפול בשגיאות.
- פריסה—פרסום דרך App Store, הגדרת עדכון מרחוק.
לוחות זמנים משוערים
המרת מודל קיים + אינטגרציה בסיסית ל-iOS—1–2 שבועות. מודל מורכב עם פעולות לא סטנדרטיות, מספר כניסות/יציאות, עדכון מרחוק—3–5 שבועות. העלות מחושבת בנפרד לכל פרויקט. אנו נעריך את המשימה ביום עסקים אחד—פשוט שלח את המשקלים ותיאור המשימה.
צור קשר לייעוץ על אינטגרציית Core ML לפרויקט שלך. בקש ניתוח מקדים של המודל שלך—נמצא את הפתרון האופטימלי.
למידע נוסף על המרה, ראה תיעוד coremltools.







