تمرين التوفيق (Fitting Exercise)
لنحاول الآن ملاءمة الدالة 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 يكون كافيًا.