تمرين التوفيق (Fitting Exercise)

Home PDF

لنحاول الآن ملاءمة الدالة y(x) = ax + b.

import numpy as np
import math
x = np.linspace(-math.pi, math.pi, 20)
print(x)
[-3.14159265 -2.81089869 -2.48020473 -2.14951076 -1.8188168  -1.48812284
 -1.15742887 -0.82673491 -0.49604095 -0.16534698  0.16534698  0.49604095
  0.82673491  1.15742887  1.48812284  1.8188168   2.14951076  2.48020473
  2.81089869  3.14159265]

لاحظ أنه linspace وليس linespace. هذا جزء من كود في مثال من دروس PyTorch. هذه الأرقام العشرية قد لا تكون واضحة بشكل بديهي.

x = np.linspace(0, 100, 20)
import numpy as np
import math
x = np.linspace(0, 100, 20)
y = np.linspace(0, 100, 20)
print(x)
print(y)

لنفترض أن لدينا مجموعتين من البيانات. كيف يمكننا تمثيلهما بيانيًا؟

خط

ومع ذلك، تبين أن x و y متماثلان.

x = np.random.rand(2)
print(x)
[0.06094295 0.89674607]

استمر في التعديل.

x = np.random.rand(2)*100
print(x)
[39.6136151  66.15534011]

استمر في التعديل.

import numpy as np
import math
import matplotlib.pyplot as plt
x = np.random.rand(10)*100
y = np.random.rand(10)*100
plt.plot(x,y)
plt.show()
<img src="/assets/images/ml/xy1.png" alt="xy1" style="zoom:30%;" />
[20.1240488  59.69327146 58.05432614  3.14092909 82.86411091 43.23010476
 88.09796699 94.42222486 58.45253048 51.98479507]
[58.7129098   1.6457994  49.34115933 71.13738592 53.09736099 15.4485691
 45.12200319 20.46080549 67.48555147 91.10864978]

يمكن ملاحظة أن النقاط هي من (20.1,58.7) إلى (59.7,1.6) ثم إلى (58,49.3). لاحظ أنه على الرغم من أن الرسم يبدو فوضويًا، إلا أنه لا يزال يحتوي على نمط. إنه رسم بخط واحد.

import numpy as np
import math
import matplotlib.pyplot as plt
x = np.random.rand(2)*100
y = np.random.rand(2)*100
print(x)
print(y)
plt.plot(x,y)
plt.show()
<img src="/assets/images/ml/x1.png" alt="x1" style="zoom:30%;" />
<img src="/assets/images/ml/y11.png" alt="y11" style="zoom:30%;" />

لاحظ أن مقياس x و y يتغير دائمًا. لذا، فإن الخطين اللذين يبدوان متشابهين، في الواقع ليسا كذلك. إذن، كيف يمكننا إيجاد a و b في المعادلة y(x) = ax + b؟ لنفترض أننا نعرف الآن نقطتين على هذا الخط. لاحظ أنه يمكننا حلها باستخدام ورقة مسودة. نطرح المعادلتين للتخلص من b، ثم نحسب a. بعد ذلك، نعوض a في إحدى المعادلات لإيجاد b.

ومع ذلك، هل يمكن استخدام طريقة التخمين؟ باستخدام طريقة التقسيم الثنائي. دعونا نجرب.

import numpy as np
import math
import matplotlib.pyplot as plt
x = np.random.rand(2)*100
y = np.random.rand(2)*100
a_max = 1000
a_min = -1000
b_max = 1000
b_min = -1000
def cal_d(da, b):
    y0 = x[0] * da + b
    y1 = x[1] * da + b
    d = abs(y0 - y[0]) + abs(y1 - y[1])
    return d
def cal_db(a, db):
    y0 = x[0] * a + db
    y1 = x[1] * a + db
    d = abs(y0 - y[0]) + abs(y1 - y[1])
    return d
def avg_a():
    return (a_max + a_min) / 2
def avg_b():
    return (b_max + b_min) / 2
for i in range(100):
    a = avg_a()
    b = avg_b()
    max_d = cal_d(a_max, b)
    min_d = cal_d(a_min, b)
    if max_d < min_d:
        a_min = a
    else:
        a_max = a
    
    a = avg_a()
    max_db = cal_db(a, b_max)
    min_db = cal_db(a, b_min)
    if max_db < min_db:
        b_min = b        
    else:
        b_max = b
print(x)
print(y)
print('a = ', avg_a())
print('b = ', avg_b())
print(avg_a() * x[0] + avg_b())
print(avg_a() * x[1] + avg_b())

قم بتشغيله.

[42.78912791 98.69284173]
[68.95535212 80.89946202]
a =  11.71875
b =  -953.125
-451.68990725289063
203.4317390671779

النتائج كانت مختلفة بشكل كبير.

لنبسط المشكلة. لنفترض أن y(x) = ax. لدينا مجموعة من القيم x, y، ونريد إيجاد قيمة a. على الرغم من أنه يمكننا حسابها مباشرة، دعنا نخمن.

import numpy as np
import math
import matplotlib.pyplot as plt
from numpy.random import rand, randint
x = randint(100)
y = randint(100)
a_max=1000
a_min=-1000
def cal_d(da):
    y0 = x * da
    return abs(y0 - y)
def avg_a():
    return (a_max + a_min) / 2
for i in range(1000):
    a = avg_a()
    max_d = cal_d(a_max)
    min_d = cal_d(a_min)
    if max_d < min_d:
        a_min = a
    else:
        a_max = a
print(x)
print(y)
print(avg_a())
print(avg_a()*x)

النتيجة كانت مُرضية. التخمين كان دقيقًا.

96
61
0.6354166666666667
61.00000000000001

ومع ذلك، عادةً ما يتم كتابة for i in range(15):، حيث أن التكرار 15 مرة يكون أكثر دقة. لماذا؟ لاحظ أن x و y لدينا كلاهما في النطاق من 0 إلى 100. وبالتالي، فإن قيمة a أيضًا في النطاق من 0 إلى 100. على سبيل المثال، x=1, y=99 و x=99, y=1. لذلك يمكن تحسين القيم الأولية لـ a_min و a_max. لاحظ أن 1/99 تساوي 0.01. لذا، ربما تكون الدقة حتى 0.01 كافية، وهذا يعني حساب 2^n بحيث تكون تقريبًا 10000. log2(10000) = 13.28. مما يعني أن تعيين القيمة إلى حوالي 14 يكون كافيًا.


Back 2025.01.18 Donate