מדריך לאוקטב Octave
למי מכם שמגיע מהקורס של למידת מכונה של Andrew Ng וגם למי שלא, ניתן פה סיקור והדרכה על השפה Octave שהיא בדומה לMatlab משמשת בעיקר לחקר ופתרון בעיות מתמטיות. אז בואו נרוץ:
לפי אנדרו, השפות שהוא ראה הכי הרבה שמפתחים איתן שיטות של למידת מכונה הן אוקטב, מטלב, פייתון, NumPy, וR. עם זאת, השפות שלרוב הכי נוחות לפיתוח אבות טיפוס של אלגוריתמים הם אוקטב ומטלב. כיוון שמטלב עולה כסף, אנדרו בחר באוקטב לתרגילים ולתרגולים של הקורס.
פעולות בסיסיות
כמו כל שפה, ניתן לכתוב פעולות פשוטות של חיבור, חיסור, כפל, חילוק והעלאה בחזקה עם הסימנים המוכרים: + – * \ ו^. ניתן גם לכתוב אופרטורים של השוואה כש== מציין "שווה ל-" ו"=~" מציין "אינו שווה ל-". AND ייכתב כ&&, OR כ||, וxor פשוט כxor(a,b).
מסמנים תגובה עם %.
טריק: בכל שורה האוקטב מחכה . ניתן לשנות את הכיתוב עם הפונקציה PS1(‘xxxx’);.
בדומה לשפות תכנות אחרות, ניתן לכתוב כמה פקודות בשורה אחת, כשפסיק מפריד ביניהם. לדוגמה a =5, b=1;
משתנים
פשוט לכתוב – a=3 ייתן ערך 3 למשתנה a וידפיס אותו כברירת מחדל. אם אתם לא רוצים את ההדפסה למסך הזו כל פעם, שימו נקודה פסיק.
אפשר להדפיס משתנים כשפשוט כותבים את שם המשתנה ולוחצים אנטר. הפלט ייראה כמו x=value. אפשר גם להשתמש בפונקציה disp(variable) כדי להציג רק את המספר למסך. פקודה כמו format long מציגה מספרים למסך עם יותר ספרות אחרי הנקודה, וformat short עם פחות (ומעגלת את הספרה האחרונה).
מטריצות
דוגמה למטריצה:
A = [1 2; 3 4; 5 6]
כל ; למעשה מוסיף עוד שורה למטריצה.
עוד סינטקס שימושי הוא כשכותבים :, לדוגמה v = 1:0.2:2, שמייצר למעשה וקטור שורה בו המספרים מתחילים מ1 עד 2 בקפיצות של 0.2. אם לא הגדרנו קפיצה (נגיד כv=1:5), הקפיצות יהיו ב1 בכל פעם.
ones(x,y) תייצר מטריצה של אחדים בגודל x על y. zeros(x,y) תעשה אותו דבר עם אפסים. בנוסף, הפונקציה rand(x,y) תייצר לנו מטריצה בגודל x על y כשכל הערכים רנדומליים בין 0 ל1. למי שמכיר את המושגים, rand משתמשת בהתפלגות נורמלית, אך קיימת פונקציה randn שמגרילה ערכים בהתפלגות גאוסיאנית כשהשונות מוגדרת ל1.
ניתן להדפיס את כל הערכים במטריצה כהיסטוגרמה עם הפקודה hist(A).
את מטריצה הזהות ניתן ליצור בעזרת eye(n) כשn הוא הסדר של מטריצת הזהות.
את המטריצה ההפיכה מקבלים עם הוספת 'תג' – A’.
הפקודהA(x,y) תיגש לאיבר במקום x,y במטריצה. הפקודה A(x,:) תחזיר את כל השורה x. כדי לקחת מספר שורות, נכניס אותן בסוגריים מרובעות – A([I,j],:) תחזיר את כל השורות i וj כמטריצה אחת.
כשנרצה להוסיף שורה או עמודה למטריצה, נוכל לצרף אותה עם הכתיבה הבאה – A = [A,[a;b;c]], או להפך אם ברצוננו להוסיף שורה. כדי להוסיף מטריצה למטריצה, נעשה דבר דומה: C = [A B], או C = [A;B].
טריק: ניתן להשתמש בA(:) כדי לקבל את כל הערכים במטריצה בתור וקטור אחד ארוך.
לפני שמתחילים, זכרו שאין חובה לזכור את כל הפונקציות בעל פה בכל רגע. תמיד ניגן לרשום help func כדי לקבל מידע על הפונקציה הספציפית שאתם מחפשים.
טיפול במידע
גודל של מטריצה – size(A), כשהתוצאה היא מטריצה של בעלת שני איברים שהם מספר העמודות והשורות. ניתן להוסיף size(A,1/2) כדי לקבל רק את השורות או העמודות, בהתאמה.
length(A) תחזיר את האורך הגדול יותר בין העמודות או השורות. לרוב משתמשים על וקטורים.
הפקודה pwd מאפשרת לנו לראות את התיקייה הנוכחית ממנה אנו עובדים. וכמו בcmd, cd ‘location’ תשנה את התיקייה הנוכחית לlocation שכתבנו, והפקודה ls תציג את התיקיות והקבצים בתיקייה הנוכחית.
אחרי שהגענו לתיקייה הרצויה, נוכל לטעון את הקבצים שלנו:
load filename.dat או load(‘filename.dat’) תטען את הקובץ הרצוי.
בכל שלב נוכל להציג את כל המשתנים בסביבת העבודה שלנו על ידי הפקודה who. אם נרצה קצת יותר מידע מאשר רק שמות המשתנים, נוכל לכתוב את הפקודה whos. נוכל למחוק משתנה מסוים על ידי clear var, או את clear כדי למחוק את כולם.
כשנרצה לשמור משהו, נשתמש בsave file.mat var כדי לשמור את המשתנה var בקובץ. אם נרצה לשמור בטקסט ושיהיה מובן, נשתמש לרוב בתבנית save file.txt var -ascii.
חישוב מידע
נניח ויש לנו 2 מטריצות A וB שגודלן זהה, נסתכל על כמה פעולות –
A .* B תחזיר את ההכפלה של איברי A באיברי B. A.^3 תעלה את כל איברי A בחזקה שלישית. באופן כללי, פעולות על מטריצות שמתחילות בנקודה (.) מכוונות לאיברי המטריצה עצמה.
הרעיון הכללי הוא שניתן לערוך פעולות על איברי המטריצה בעזרת מספרים ספציפים וגם בעזרת איברים של מטריצה אחרת.
דוגמות:
2 ./ A תיתן לנו מטריצה בה כל האיברים שווים ל2 חלקי האיברים המקוריים בA. log(A) או exp(A), כדי להחזיר מטריצה מתאימה של הלוגריתם של כל האיברים, או e בחזקת האיברים (אקספוננט). abs(A) תחזיר מטריצה עם ערכים מוחלטים לכל האיברים.
אפשר גם עם מספרים – הפעולות B + 4, B*3, יוסיפו או יכפילו כל אחד מאיברי B, וכן הלאה.
מציאת מקסימום או מינימום של מטריצה מבצעים על ידי max(A) או min(B). ממוצע עם mean(B). sum(A) תחזיר את סכום האיברים, וprod(A) את מכפלתם.
עניין שחשוב לשים לב אליו בmax (ובmin) הוא שכאשר אנו מתעסקים במטריצה שהיא אינה וקטור, סתם כך הפקודה max(B) תחזיר את השורה שבה נמצא המספר המקסימלי. ומכך, max(A,[],1/2) תחזיר את השורה\העמודה בה נמצא המספר המקסימלי. כדי להחזיר רק אותו, ניתן לבצע max(max(A)).
floor(A) או ceil(A) מעגלים למטה או למעלה
את איברי המטריצה.
ניתן גם לערוך פעולות השוואה, בדיוק כמו על מספרים רגילים – A < 4 תחזיר מטריצה בה כל איבר הוא 1 אם האיבר המקורי קטן מ4 ו0 אם הוא לא. הוספת הפקודה find(A<4) תחזיר מטריצה עם האינדקסים שעונים על הקריטריון.
magic(n) יוצרת מטריצת קסם (סכום כל שורה, עמודה או אלכסון שווה) בגודל nxn.
שרטוט פונקציות
אחד מהכלים השימושיים בלמידת מכונה ובחקר פונקציות הוא האפשרות לשרטט את הפונקציות והערכים עצמם, ללמוד ולהסיק מהם מסקנות.
נניח שיש לנו וקטור של ערכים v כזה- v = [1:100]. נגיד עבורו y = sin(2*pi*v). נקבל את y כוקטור בו כל תוצאה נערכה לפי הסינוס שכתבנו.
plot(v,y1) תציג גרף של ערכי y1 כפונקציה של ערכי v. אם נרצה להוסיף פונקציה נוספת לשרטוט בלי למחוק את הקודמת, נקליד hold on; ונוסיף שרטוט נוסף. ניתן לשנות את הצבע על ידי הוספת מחרוזת בצורה הזו – plot(v,y2,’g’) שישרטט את y2 בירוק.
כדי לשמור את הגרף(ים) נעשה print -dpng ‘myPlot.png’.
עיצוב וסידור
xlabel(‘wh’) וylabel(‘at’) יוסיפו תווית מתחת לציר הx והy, בהתאמה. title(‘my graph’) יוסיף כותרת, legend(‘first func’,’sec func’) יוסיף מקרא.
תנאים, לולאות ופונקציות
בקצרה ניתן לומר, שההבדל באוקטב הוא שבמקום סוגריים מסולסלות בשפות אחרות, כל פקודת תנאי או לולאה מסתיימת בפקודה end;. כך ש-
לולאת for פשוטה נראית כך:
For “statement”, do something; end;
כאשר בהתחלה כותבים את תנאי הלולאה, פסיק, לאחר מכן את הפעולה בכל איטרציה ונקודה פסיק, והוספת פקודה end; בסוף.
נגדיר sum = 0. ונריץ for i=1:10,sum=sum+I; end; כדי לקבל את סכום המספרים מ1 עד עשר.
לולאת while עובדת בצורה דומה –
while “statement”, do something; end;
כנ"ל לגבי if – if A(2)==1,disp(‘value is one’); end;
פונקציות, לעומת זאת, מוגדרות כקובץ משל עצמו – כדי ליצור פונקציה, ניצור קובץ חדש בשם myfunc.m ובתוכו נכתוב את הפונקציה שלנו בצורה הבאה:
function y = squareNum(x)
y = x^2;
כשfunction y מציינת שזו פונקציה ואת שם הערך המוחזר, וsquareNum(x) הוא שם הפונקציה עצמה. לאחר השורה הזו כותבים את הפונקציה המלאה.
באוקטב ניתן בין היתר לקלוט או להחזיר מספר איברים, שלא כמו בכל השפות:
function[y1,y2] = squareAndCubeNum(x)
y1 = x^2;
y2 = x^3;
כיוון שאנחנו עובדים מתוך קובץ, חשוב לוודא שאוקטב מוצאת את הפונקציה כדי שהיא תוכל להשתמש בה. את זה ניתן לעשות או על ידי פקודה לעבוד מתוך התיקייה בה הפונקציה עצמה נמצאת (עם cd), או בהוספת כל המיקום עצמו לרשימת המיקומים ממנה אוקטב תחפש דברים, על ידי addpath(‘yourpath’).
וקטוריזציה
בשפות עיליות רבות, וביניהן אוקטב, יש ספריות מאוד יעילות לחישוביים מספריים של ערכים ומטריצות. כיוון שהרבה מהנוסחאות בקורס בסופו של דבר מתעסקות במטריצות, אין תמיד צורך לחשב ערכים נקודתיים בלולאות, אלא ניתן ישירות לחשבן על ידי כפל מטריצות, שגם ייקח פחות שורות קוד וגם יהיה יותר יעיל.
לדוגמה, במקום לרוץ בלולאה ולחשב לכל ביטוי את הת'טות שלו, נוכל להכפיל את המטריצה X במטריצה ת'טה ולקבל מטריצה חדשה עם כל הערכים מחושבים מראש, וכן הלאה.
מקווים שנהנתם מה מדריך לOctave אוקטב . עד לפעם הבאה!
