<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Maria Khelli on Medium]]></title>
        <description><![CDATA[Stories by Maria Khelli on Medium]]></description>
        <link>https://medium.com/@khelli07?source=rss-e5fa95713910------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*WJtjvTxyvTKw1yR7Od0Aew.jpeg</url>
            <title>Stories by Maria Khelli on Medium</title>
            <link>https://medium.com/@khelli07?source=rss-e5fa95713910------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 31 May 2026 18:43:28 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@khelli07/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Spending This Summer as a Google Summer of Code Contributor at Rocket.Chat ]]></title>
            <link>https://khelli07.medium.com/spending-summer-as-a-google-summer-of-code-contributor-at-rocket-chat-5d194b08df1c?source=rss-e5fa95713910------2</link>
            <guid isPermaLink="false">https://medium.com/p/5d194b08df1c</guid>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[google-summer-of-code]]></category>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[gsoc]]></category>
            <category><![CDATA[rocket-chat]]></category>
            <dc:creator><![CDATA[Maria Khelli]]></dc:creator>
            <pubDate>Sun, 22 Sep 2024 14:41:38 GMT</pubDate>
            <atom:updated>2024-10-01T15:31:08.916Z</atom:updated>
            <content:encoded><![CDATA[<h3>Spending Summer as a Google Summer of Code Contributor at Rocket.Chat 🚀</h3><blockquote>This article will consist of a little bit of my story for the 2024 GSOC. But mostly it’s about my project, my learnings, and my gratitude!</blockquote><blockquote>See my project repository <a href="https://github.com/RocketChat/Apps.Smart.Scheduler">here</a>.</blockquote><h3>The Journey</h3><p>I was amazed by GSoC since I was in my first year, when my friend, Morenzoe, told me about it. Year after year, I always let it pass on it given the name “Google” and its competitiveness, the doubts about my ability, as well as my hectic schedule. However, on a random afternoon in my final year, I saw a friend, Mazaya, who was sharing his GSOC experience. Realizing it would probably be my last chance to register GSOC, I decided to give it a shot.</p><p>Giving it a shot does not mean I did not have anything else to do. I was on an internship exchange abroad while still doing my thesis remotely. But the thoughts of regretting without trying pushed me forward.</p><p>Unlike other people who might have already known which organization to go to, I was the exact opposite. Besides that, I was also a bit late by timeline, since usually people start contacting the organizations months before the registration date is open. So, every time I came back from work, I look up to every possible project that I am interested in. Some projects already have someone working on them, some are out of my scope, and some others seem hard to contact (e.g. government-related organizations).</p><p>Long story short, I found Rocket.Chat and its potential projects. One project that intrigued me was <strong>Smart Scheduling App</strong> because it is related to a thesis I am working on. FYI, I am working on continuous multilingual learning on a MASSIVE dataset, which contains the instructions for a personal assistant like Alexa!</p><p>What is more interesting is that the project was recently added. So, not a lot of people had already discussed it. <em>Such a right time for me?</em> Hence, without hesitation, I started the discussion with the mentors and started working on the proposal right away. And with that, my search for the project is done. I decided to only focus on one proposal and let the universe work on the rest.</p><p>The rest: the proposal got reviewed by a mentor → I revised → I submitted → I got called for an interview! I was delighted because Rocket.Chat team was also enthusiastic and very responsive :)</p><h3>The Project</h3><h4>Overview</h4><p>Smart scheduling app is an assistant tailored for meetings, reminders, and schedules. It is connected with Google Calendar via function calling so you can query and create meetings directly from the Rocket.Chat app.</p><p>Mentors: Sing Li, Devanshu Sharma, and Douglas Gubert</p><p>Tools used: Ollama, Google Calendar API, Mistral, LLaMA3/3.1.</p><h4>Background</h4><p>There are 2 aspects that motivate the development of this project:</p><ol><li><strong>App-wise</strong>: potential enhancements for existing Google Calendar plugin.</li><li><strong>Research-wise</strong>: API integration with LLM, testing more robust solutions for math problems with function calling (e.g. finding the common time for all of the members).</li></ol><h4>User Stories</h4><p>Here are the user stories (slightly adjusted compared to the ones in the proposal).</p><ol><li>As a user, I want to be able to <strong>trigger </strong>a scheduling event by <strong>using the slash command</strong>.</li><li>As a user, I want to be able to <strong>give my prompt</strong> to the app to <strong>schedule a meeting</strong> or <strong>make a reminder</strong>.</li><li>As a user, I want to be able to <strong>specify </strong>who will be the<strong> participants of the meeting</strong>.</li><li>As a user, I want to be able to <strong>receive one schedule suggestion</strong>.</li><li>As a user, I want to be able to <strong>pick one of the meeting schedule suggestions</strong>.</li><li>As a user, I want to be able to<strong> choose the LLM used</strong>.</li><li>As a user, I want to be able to <strong>regenerate a result if the AI hallucinates</strong>.</li></ol><h3>The Results</h3><p>These are the implementation of the app which is done through Rocket.Chat apps engine. Each feature will have its corresponding description, solution, diagrams, as well as screenshots.</p><h4>Feature 1: Create a meeting</h4><p>This feature will allow users to schedule a meeting. The app will accept a prompt from the user and it will generate a time recommendation based on it.</p><p>Related user story: 1, 2, 3, 4, 5, 7</p><h4><em>Solution</em></h4><p>The user can trigger a prompt modal through the `/schedule` command that is implemented with `<strong>ISlashCommand</strong>`. The modal will ask you for the <strong>prompt</strong> and the <strong>participants</strong>. The decision behind using modal instead of just bare slash command was the UX. With a modal, the app can show the user a guide and example of how to make a prompt to achieve desirable output.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xJY8LyE1IGSSOdxdAqrP3w.png" /></figure><h4>Diagram</h4><p>The normal user flow for this feature is as follows.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/981/0*suIE3YZyv41rcaLw" /></figure><p>When the user clicks the “Schedule” button on the prompt modal (blue box), these are the processes between the app and the LLM:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/816/0*_a91rL1ekq51Aeok" /></figure><p>Let’s say we use the following prompt as an input.</p><p><em>Could you arrange a meeting for the next Wednesday? We need to discuss about the new AI projects, and I would prefer an early slot for fresher mind.</em></p><p>and let’s say we have persons A and B as specified participants. Here is the walkthrough:</p><ol><li>The app will make a first call to LLM. It will detect the user’s preference for date and time. In this case, if today is Saturday, 21 September 2024, then a) the preferred date will be next Wednesday, 25 September 2024, and; b) the preferred time is 09.00–12.00 in the user’s local time (morning).</li><li>The app will call Google Calendar API for the free-busy schedule of the user, person A, and person B.</li><li>The response of Google Calendar API will be processed and fed to the algorithm. Along with that, we also specify the preference of the user. It will be the constraint for the search space.</li><li>The algorithm will output available times as well as its corresponding participants who are available at that time. Based on this result, the app will make a call again to the LLM to get one recommendation.</li></ol><h4>Screenshot</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/940/0*eESo_2HcrgHmPO9i" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/929/0*BQzXxlCMd3SNHukk" /></figure><h4>Feature 2: Setting a reminder</h4><p>This feature allows the user to set a reminder for themselves or for their team.</p><p>Related user story: 1, 2, 3, 4</p><h4>Solution</h4><p>This feature is similar to the previous one. However, since this is a reminder, we do not need to calculate the common time. The user can specify any time they want and the app will create the reminder based on that without considering the busy time or schedules of the participants.</p><p>For now, this flow<strong> is only triggered if the user specifies the word “remind” in the prompt</strong>. (Ideally, the <em>intent</em> should be detected by the LLM!)</p><h4>Diagram</h4><p>The normal user flow for this feature is as follows.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/761/0*FzGnLL25naXBFY7p" /></figure><p><em>The logic flow of this feature is not shown as the app only makes one call to the LLM before outputting to the user.</em></p><p>Unlike the previous feature, the app does not make a call to find a common time in this feature (the reason is mentioned in the previous section). The app only does the <strong>first step</strong> on the previous feature, which is to <strong>detect the preferred date and time</strong>. After that, the recommendation is immediately outputted to the user.</p><h4>Screenshot</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0ioMKjioNyok8epn" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/770/0*AjBTY96n6fK4YB4y" /></figure><h4>Feature 3: Asking a question</h4><p>This feature was implemented <em>last minute</em> because I felt I did not do “function calling” like it should be. If you see the previous features, you can sense that the program already <strong>knows which function to call </strong>because of its determined flow. For me, I think this can be solved by just asking the LLM to output a JSON format for the arguments. However, I felt like I did not use the fact that LLM could choose which function to use (it was not suitable for the previous implementation).</p><p>Related user story: None,<em> this is an addition</em></p><h4>Solution</h4><p>Since this is was only developed quickly (because of the time), the app only provide for one type of question to answer which is “What is the schedule of a person”. However, I think this feature should be easily extended by just registering the function and appending the function definition in the code.</p><p>Personally, I find this one quite simple, yet interesting. Since Rocket.Chat app does not allow a lot of external libraries to be integrated into the system, I used a workaround with a JSON-mode output. Basically, I give the LLM the list of the functions along with its arguments. When the LLM outputs the JSON, I parse it into the following.</p><pre>export interface IFunctionCall {<br>    functionName: string;<br>    arguments: {<br>        [key: string]: any;<br>    };<br>}</pre><p>Then, we register the function as follows.</p><pre>const functionsMap = { <br> theFunctionName: async (): Promise&lt;...&gt; =&gt; {} <br>}</pre><p>Let’s say that we have a function named `<strong>getFunction</strong>` which outputs an object of `<strong>IFunctionCall</strong>`. Then, we just need to call it like this.</p><pre>getFunction(this.app, this.http, this.sender, question).then(<br>    (res) =&gt; {<br>        functionsMap[res.functionName]({<br>            app: this.app,<br>            http: this.http,<br>            user: this.sender,<br>            ...res.arguments,<br>            roomMembers: members,<br>        }).then((res) =&gt; {<br>            // Do something<br>        });<br>    }<br>);</pre><h4>Diagram</h4><p>Unlike the previous 2 features, which use modals, this feature is triggered by only a slash command of a format `/schedule ask &lt;the_question&gt;`. Here’s a rough flow on how the app works.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/841/0*DXxB0dQByAwkv0S3" /></figure><h4>Screenshot</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/953/0*HpBMln59TvJwYk5b" /></figure><h4>Feature 4: Specifying which LLM to use through settings</h4><p>This feature allows users to have more flexibility in choosing the model.</p><p>Related user story: 6</p><h4>Solution</h4><p>Adding settings through the `<strong>extendConfiguration</strong>` method on the App. The setting must be specified using its interface, `<strong>ISetting</strong>` from the apps engine. Users can specify the model by choosing one of these options. The model choices are the ones provided in the Rocket.Chat SAFE environment.</p><h4>Screenshot</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*hWa_1SliIlg1-Svg" /></figure><h3>The Limitations</h3><h4>On Rocket.Chat</h4><p>While developing the app, I found several limitations or inconveniences that RC could consider for further development. <em>(Please let me know if any of this is already fixed/implemented. Maybe I missed it.)</em></p><ol><li>Short (or unadjustable) timeout on an API call. Often the app detects that an error has occurred while in fact, the app was just waiting for the LLM output (it is normal for an LLM to process a bit longer than usual API call). However, this can be fixed using `then-catch` instead of `async-await`.</li><li>Short trigger ID lifespan. With a short trigger ID lifespan, the app can not jump from one modal to another even though the app already used `then-catch` to overcome the timeout.</li><li>No autocomplete yet on modal (minor).</li><li>Hard to use an external library, hence we can not utilize popular libraries such as LangChain.</li></ol><h4>On Environment</h4><p>I think because I only use my local laptop, it is hard to work on bigger LLM. Rocket.Chat does provide the dev environment that we can use (we call it SAFE environment). However, the disadvantage is the developer can not see the app logs, so it is harder to debug. Besides that, other developers also use the environment. Sometimes, an app crashes so it affects other apps (dependency problem).</p><h3>The Takeaways</h3><h4>Me, Myself, and I</h4><p>Throughout my experience in GSOC, I learned:</p><ol><li>To communicate more clearly.</li></ol><p>Since English is not my first language, sometimes I can get confused when someone says something implicitly. Hence, I learn to ask and confirm my understanding. If I did not know the context, I would research it first and get back to the mentors asynchronously.</p><p>2. To be more active and more explorative.</p><p>Sometimes, my solutions are very simple and not so out of the box. My mentors, especially Sing Li, always give advice that I have not thought of before. This encouraged me to be more explorative of the approaches to the problems.</p><p>3. To keep writing documentation structurally.</p><p>I got some positive feedback from my documentation, especially on how I showed the presentation on demo day. This motivated me to do keep doing on it and do more of it.</p><h4>The prompting</h4><p>Based on the prompting I did, I discovered several things:</p><ol><li>You need to specify OVER and OVER again for the LLM to “obey”.</li></ol><p>This is what I learned from the <a href="https://tensortrust.ai/">tensortrust</a> practice that one of my mentors, Devanshu, was sharing a while ago. For example: “Do not specify X. Only use A, B, and C. It is forbidden to use X. ” (and so on).</p><p>2. AI is not good at counting (duh).</p><p>It tends to hallucinate, especially on the smaller model. For example, in this project, I asked the LLM to determine the date of “next Friday” given today is <em>X_DATE</em>. Here’s what I tried:</p><p>a) Giving it a chain of thought. Asking it to count date by date;</p><p>b) Specifying the next 14 days, from the name of the day to the date, month, and year.</p><p>The result: the second approach is better!</p><p>3. For a function calling to work better on complex use cases, you might want to consider making 2 calls.</p><p>In the first step, make the LLM think and explain the answer. Then, in the second step, make a call for function calling based on the first step. If you only use the second step, the potential problems are: you do not know why the LLM outputs it that way and it will be hard for you to debug and fine-tune the prompt.</p><p>When you know the thoughts of the LLM, you know the mistakes it often made. With this information, you can give a few shot examples so the LLM has less tendency to make mistakes.</p><h4>The project</h4><p>As a solo developer of this project, I realized that the app is not on the level of robustness yet to be delivered to production. Here are some problems that I often encounter while developing the app. Mostly it is due to the indeterministic nature of the LLM.</p><ol><li>The LLM outputs an invalid JSON.</li></ol><p>I <em>adjusted</em> the function calling. Instead of using the library (<a href="https://platform.openai.com/docs/guides/function-calling/function-calling-with-structured-outputs">like in </a>Python), I used the LLM to specify the arguments based on the prompt. This argument should have output in JSON, so it can be fed to a function.</p><p>The disadvantage of this approach is inconsistency. With one prompt it can get valid JSON, but with a different prompt, it might output invalid JSON which makes an error.</p><p><em>Why don’t you use API format instead? </em>I only use Ollama to develop, so it is different than the OpenAI request format.</p><p>2. The LLM gives incorrect or unrelated suggestions.</p><p>By incorrect I mean for example the LLM gives a wrong date preference. By unrelated I mean when the LLM picks a time that was not on the list of common time choices as a recommendation.</p><p>Solution? For now, I can not think of anything other than doing more research, trying more approaches, or using bigger LLMs.</p><h3>The Closing Notes</h3><p>I am very thankful for the opportunity given to me as a contributor to the 2024 Google Summer of Code in Rocket.Chat. It surely exposed me to the technologies I otherwise would not explore myself. I am also deeply thankful for the guidance, advice, and time spent reviewing my work by my main mentors: Sing Li and Devanshu. I hope I can still keep in touch with the Rocket.Chat team, albeit the program has come to an end.</p><p>Written with ❤️,</p><p>Khelli.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5d194b08df1c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Journey to Singapore: Pursuing Dreams, Embracing Challenges, and Finding Purpose]]></title>
            <link>https://khelli07.medium.com/journey-to-singapore-pursuing-dreams-embracing-challenges-and-finding-purpose-bcf6c4dff2a1?source=rss-e5fa95713910------2</link>
            <guid isPermaLink="false">https://medium.com/p/bcf6c4dff2a1</guid>
            <category><![CDATA[reflections]]></category>
            <category><![CDATA[dreams]]></category>
            <category><![CDATA[singapore]]></category>
            <category><![CDATA[growth]]></category>
            <category><![CDATA[exchange]]></category>
            <dc:creator><![CDATA[Maria Khelli]]></dc:creator>
            <pubDate>Sat, 06 Apr 2024 07:55:18 GMT</pubDate>
            <atom:updated>2024-04-07T15:04:08.716Z</atom:updated>
            <content:encoded><![CDATA[<p>To settle for a life in Singapore is one of my biggest dreams. To achieve that, I have to knock on the doors and find a way to get in. Well, I did try several things, including applying to NTU as an art and design student (oops why am I in CS now) and applying for IISMA (Indonesian’s government fully-funded exchange program), but I failed all of them.</p><p>Apparently, the clocks I have counted in to study, write the essays, and create the portfolios, were not enough to get me in. The first failure was a mess, but the second one was easier to move over with. I thought, “Maybe the time has not come yet.”</p><p>The third time is a charm, they said. So I tried another program, called NUS Overseas College (NOC). It was introduced by my friend, Vito Christian — and I thank him for that. NOC is a program where you will have an internship in a start-up and a Venture Creation class. The purpose of this program is to nurture students with an entrepreneurial mindset. It was never in my plan to apply for this program. I thought it would end with IISMA by the time I finished my undergraduate.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fl8MHEZL2Y-Ssbgb1i8ESw.jpeg" /><figcaption>Me @ NUS University Town</figcaption></figure><h4>Getting into Singapore as an Exchange Student</h4><p>The program selection began with the university-level first. After that, all we need to do is secure a job. Because I am from a Computer Science background, most of the roles I applied are software engineering. The recruitment process is quite the same as the one I previously had, but simpler since the companies were relatively small. But, to increase my chances, I made myself go the extra mile as I built my personal website and tidied up my GitHub. However, talking in English in a professional setting was new to me. So, all I could do was practice. After several interviews, I managed to secure two offers one month before the deadline. I was very thankful to be able to secure it early.</p><p>I recall our program managers, Yu Lin, and Tun Leng, reminded us about the hard and harsh life in Singapore, but it does not scare me because I have the confidence that I will be able to get past everything as I lend God’s strength. Turns out, yes, everything is still manageable until now. Even several people said to me, “You look very happy!” Yes, how can I not? I am one step closer to my dream :)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*m_D6nrPjLpA07rTZ_F8IMw.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/945/1*loS-rtH8wttTGe3oHqqCGA.jpeg" /><figcaption>NOC Sharing Session (left) and NOC Orientation Day (right)</figcaption></figure><h4><strong>What I learned here so far</strong></h4><p>Being able to be part of NOC is such an honor to me. I met a lot of new friends, experienced new things, and gained new perspectives. This journey has allowed me to change my mindset for a lot of things, especially entrepreneurship. I initially was not interested in start-ups at all and already set my mind to just be a corporate slave since I think it is less risky than a start-up.</p><p>But now, who knows? Maybe I will try to take more risks. Maybe one day I will start my startup, or be a co-founder of something. To be able to work and grow on your own idea is a different thing than just doing daily sprints, ticking up tasks, and talking to your bosses.</p><p>Living in Singapore also helps me see the things I never encountered before. Being hectic here makes me much more appreciative of the simple things, such as being able to have a warm shower after a long day, to sip a good cup of coffee in the morning, or to find good cheap food around. And of course, I also see some of the privileges I miss of being in Indonesia: ojek online and cheap fruits!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*H5MCIiIUezTyJYBVrEa23g.jpeg" /><figcaption>Supporting my Palembang fellows for their theatre show!</figcaption></figure><h4>Closing</h4><p>Failure after failure once made me think of how unfortunate I am. However, after the time goes by, it came to me that I was actually lucky. Imagine if I were to enroll into NTU Art and Design, I would probably never be able to take tech opportunities now. Imagine if I got accepted to IISMA, I would never be able to have an experience working on-site overseas.</p><p>As I reflect, I am filled with gratitude for the unwavering support of my family, friends, and mentors The journey here has not yet ended, but it just barely started. More challenges will come and more lessons ought to be learned. I believe it will lead me to the right place as long as it is done with trust and determination.</p><p>Praise be to God!</p><blockquote>“Only those who risk going too far can possibly find out how far one can go.”<br>— T.S. Eliot</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bcf6c4dff2a1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Being a Speaker “Soft Introduction to Vector Database” as an Intern]]></title>
            <link>https://medium.com/tiket-com/being-a-speaker-as-an-intern-soft-introduction-to-vector-database-c0787874ba22?source=rss-e5fa95713910------2</link>
            <guid isPermaLink="false">https://medium.com/p/c0787874ba22</guid>
            <category><![CDATA[data]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[vector-database]]></category>
            <category><![CDATA[search-engines]]></category>
            <category><![CDATA[database]]></category>
            <dc:creator><![CDATA[Maria Khelli]]></dc:creator>
            <pubDate>Sun, 04 Jun 2023 23:47:25 GMT</pubDate>
            <atom:updated>2023-07-09T07:39:13.950Z</atom:updated>
            <content:encoded><![CDATA[<p>Few weeks ago, I was having a biweekly meeting with one of the DS Leads. At the same moment, she suddenly asked me to be a speaker in our upcoming internal sharing sessions. Usually, the speaker is the full time employees, leads, or even managers. Sometimes, interns also get the chance at the end of his/her contract. Hence, I really was not expecting that since my contract was not ending in any time soon (at that time). But, oh, well, I am still blessed to have such a great opportunity.</p><p>When I wrote this article, I was working for PT. Global Tiket Network, known as tiket.com in Indonesia. Here, we have sharing sessions conducted regularly as a part of our culture. Every sharing session will have different presenters and different topics. The topic is up to the speaker, but I was not sure what I should talk about since our team is filled with Masters and PhDs. I thought most of my knowledge would already be covered by them because I even have not completed my undergraduate.</p><p>Therefore, I asked my mentor for advice. He told me to talk about Vector Database since it is a relatively new tool for us. So, other members might not know about it. Still, I was in doubt since it is also novel to me, but I am willing to learn about it. To convince me, my mentor said, “It does not have to be detailed and expert. Just present it as an <em>fyi</em> knowledge. It is to let DS fellows know that we do have this kind of technology. With that, we can expand our possible solutions.”</p><p>… and so I took the chance.</p><p>First few days researching it was overwhelming for me since I did not know which to read first. But, several days later, I started to get a bit grasp on it. So, from this point forward, I will give a brief summary about Vector Database based on my little research. <em>Disclaimer: I am also very new to this topic. Thus, I may miss some details and some information may be inaccurate. Feel free to correct me! </em>:)</p><h3>What is a Vector Database?</h3><p>Vector database basically has a similar function to traditional database, but imagine it this way: it has <strong>a special column that can store vector embeddings</strong> and use it for fast retrieval and similarity search. With that in mind, vector databases are also <strong>built with the utility to create, read, update, and delete</strong> (CRUD) as it is done in traditional databases.</p><p>In addition to what I have mentioned above, vector databases have <strong>metadata filtering</strong>. Thus, when we <strong>are querying with vector embeddings</strong>, we can filter our result based on the metadata.</p><p>For example, let’s say that we have a database that stores a lot of apparel. When we want to search for similar items with [1, 0.2, 0.8, …, 0.6] embedding, we can specify the price or the color. So, in natural language, we would command the vector database to</p><blockquote>“Hey, please search for whatever items that are priced under $100 and colored red, but similar (or near) this embedding [1, 0.2, 0.8, …, 0.6].”</blockquote><p>There are 3 <a href="https://zilliz.com/learn/attribute-filtering">methods</a> for this metadata filtering: pre-filtering, in-filtering, and post-filtering.</p><p>Scalability wise, they have <strong>horizontal scaling</strong> functionality. As it is common with traditional databases, some of them implement <strong>sharding</strong>, and some others are built on top of <strong>Kubernetes</strong>! So scalability should not be a big concern?</p><h3>Why Vector Database?</h3><p>As you may have seen in the previous section, vector databases are powerful when it comes to utilizing embedding for similarity search. Now, the question is, <em>Aren’t they the same as the ones that Elasticsearch has? Those TF-IDF or BM25?</em></p><p>The answer is: <strong>no</strong>, they are not the same. Hence, we need to differentiate between <em>keyword search</em> and <em>vector search</em>. Suppose we want to search for an image with input query. For <strong>keyword search</strong>, we might get</p><ul><li>Query: <strong>Dog cuddling with cat </strong>on the grass</li><li>Result:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/477/1*sLg2QNPYh7TtiLO8ef_zEQ.jpeg" /></figure><p>I mean, it is not totally wrong, they still look cute anyway! But, that is still acceptable, not correct. Try to compare it with vector search,</p><ul><li>Query: Dog cuddling with cat on the grass</li><li>Query embedding: [0.07289, -0.227076, 0.20138, …]</li><li>Image embedding: [0.08213, -0.271234, 0.01812, …]</li><li>Result:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/637/1*T6WLsW80AfuFNRXPe1h1Sg.jpeg" /></figure><p>See the difference? :)</p><p>The keyword search might only depend on the description or the title of the image. However, when the description and the title are not representative of the image, we can’t find them using keyword search.</p><p>Other than that, keyword search has <strong>several disadvantages</strong>. Ask yourself these questions:</p><ol><li>Algorithms like TF-IDF are only available for texts. <em>What if your data are images, videos, or audios?</em></li><li>TF-IDF is also known to <em>suffer with word ordering</em>. How do you distinguish “Trip from Japan to Rome” from “Trip from Rome to Japan”?</li></ol><p>These problems motivated us to utilize vector search (which is powered by vector databases). Other than that, <strong>vector databases also have more power when it is related to distance</strong>. For instance, it can:</p><ul><li>Deduplicate: eliminate similar or near-duplicate records.</li><li>Detects anomalies a.k.a. “reverse near”: find distant objects.</li></ul><p>Now that you have an understanding of keyword search vs vector search, you might want to know <strong>the difference between traditional databases and vector databases</strong>. In a nutshell, traditional DB returns <em>exact match</em>, while vector DB can return <em>near-neighbors</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*U2dcLK0PIpxGSJunT2Lt1w.jpeg" /></figure><h3>More on Vector Databases</h3><p>Other things that you may find interesting is the vector search pyramid. I got this vector search pyramid from <a href="https://dmitry-kan.medium.com/">Dmitry Kan</a>. It explains the stacks that you can use with vector databases.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1018/1*WN_AZLrAz1CHyVSBCHYN9A.jpeg" /></figure><p>We start to read the pyramid from the lower level,</p><ul><li><strong>KNN / ANN algorithms</strong>: this empowers the vector databases to query using certain algorithms. So, in natural language, we might say,</li></ul><blockquote>“Hey, please find K nearest neighbors for this [1, 0.2, 0.8, …, 0.6] embedding using XXX algorithm.”</blockquote><p>Usually, vector databases use <strong>approximate</strong> nearest neighbors since <strong>KNN algorithm is exhaustive and is not efficient for most use cases</strong>. Several vector databases such as Milvus or Qdrant has HNSW (hierarchical navigable small world) algorithm as a built-in indexing algorithm.</p><ul><li><strong>Vector databases</strong>: other than having built-in indexing algorithms, it has other capabilities to do metadata filtering and horizontal scalability (as I have mentioned before).</li><li><strong>Neural frameworks</strong>: frameworks help developers to build end-to-end search systems. It can be useful in integrating vector databases and encoders.</li><li><strong>Encoders</strong>: generate embedding for unstructured data, such as images, texts, videos, or audios. This embedding can be used when saving data to a vector database or when a user queries something (user text input is translated to embedding first, then the embedding is queried to vector database).</li><li><strong>App and user interface</strong>: self explanatory.</li></ul><h3>Examples of Vector Databases</h3><p>For the vector database examples, I took heavy reference from <a href="https://towardsdatascience.com/milvus-pinecone-vespa-weaviate-vald-gsi-what-unites-these-buzz-words-and-what-makes-each-9c65a3bd0696">this article</a>. I have not yet explored and studied each database in detail. The author also shared his knowledge through <a href="https://www.youtube.com/watch?v=Yo-AzVpWrRg&amp;ab_channel=Pinecone">a talk</a>. So, I think it is wiser for you to visit that page as well! :D</p><h4>Vector Databases Benchmarks</h4><ol><li><a href="https://qdrant.tech/benchmarks/">Benchmark by Qdrant</a></li><li><a href="https://github.com/erikbern/ann-benchmarks#evaluated">More generalized benchmark</a></li></ol><h3>Quick Demo / Tutorial</h3><p>For the demo, I used <a href="https://milvus.io/">Milvus</a> as a vector database and <a href="https://github.com/zilliztech/attu">Attu</a> as its management tools. Both can run locally using <a href="https://www.docker.com/">Docker</a>. The purpose of this section is to <strong>demonstrate how we can query a vector database using index and vector embedding</strong>.</p><h4>Milvus</h4><p>1. Download Milvus docker-compose.yml <a href="https://github.com/milvus-io/milvus/releases/download/v2.2.8/milvus-standalone-docker-compose.yml">here</a>.</p><p>2. Run the following command. Use `sudo` if you are using Linux.</p><pre>docker compose up -d</pre><p>It will start to gather the resources to have the container up and running. Just wait until the process is finished. Because I am using Windows, my screen looks like this when it is finished.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bEKyYrJIErn7jzrPNXtvOA.jpeg" /></figure><p>3. Check the status using the following command.</p><pre>docker ps</pre><p>It should look like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_c7LdX-BqPrGdd02rJ_RfA.jpeg" /></figure><p>4. You are done with Milvus, let’s move on to Attu.</p><h4>Attu</h4><p>1. Running Attu is simple, just type</p><pre>docker run -p 8000:3000 -e HOST_URL=localhost:8000 -e MILVUS_URL={YOUR_LOCAL_IP}:19530 zilliz/attu:latest</pre><p>To get local IP, you can check using <strong>ipconfig</strong> on the terminal.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/745/1*eJJrp5fVgcuuYZbiEJSp0A.jpeg" /></figure><p>2. After some time, you will see on the terminal</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yWvUtaX5x2onGHu5tQ0tng.jpeg" /></figure><p>and you can open Attu at <a href="http://localhost:8000/">http://localhost:8000/</a>. You can close the terminal now. Let’s continue on Attu Dashboard.</p><p>3. On Attu, you will see something like this. Login using the IPv4 address and port of Milvus. For me, I don’t set the username and password for Milvus, so I leave it empty.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/489/1*sNTCFb7xDGNhTbqe4TICpA.jpeg" /></figure><p>4. Let’s try to make a simple book collection. On the dashboard, open the Collection page. Navigate using the left navbar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/913/1*B6vIMfKffzX-qFYWopZ_BQ.jpeg" /></figure><p>5. Click on `Create Collection`. I will use the following schema. Feel free to modify and explore yourself. Click Create when you are finished.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/942/1*KWJXBvaOHYj81euRvO09KA.jpeg" /></figure><p>6. After that, we will create the index. Click on the Book collection. On the `embedding` column, click `CREATE INDEX`. We will use IVF_FLAT for this one.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/466/1*DtG2CFEKUZSN0viYiyjQLA.jpeg" /></figure><p>7. Then, we want to import data for the book, so we will prepare a csv. The CSV should contain embedding, title, and is_available (all columns other than id since our id is <em>auto generated</em>). Here is my example.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/936/1*5Ijr7WnUttltNB0aCnKqUQ.jpeg" /></figure><p>8. After that, we import the data using Attu.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/667/1*l6i7yVT_noaWkV-_X_apKA.jpeg" /></figure><p>Choose the CSV file you have created &gt; Next &gt; Import Data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/861/1*yOCYCmc92z0JG8vG0wZVHA.jpeg" /></figure><p>9. Hover on the Book collection, you will see on the right-hand side there is a `load` button. Click on that.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lnMi02etYCvg5YNoVg44NQ.jpeg" /></figure><p>10. After it says `Loaded`, you can move to the `Vector Search` page using the navbar. Choose the Book collection and input the vector embedding. I will query using one of the embeddings in my data. Hence, the first nearest result expected should be having the distance of 0.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vVxehVtOelz_utN_fbJAzA.png" /></figure><p>Yeay, you have successfully completed the demo! Feel free to explore more than this! :)</p><h3>Acknowledgement</h3><ul><li>Thank you Ci <a href="https://www.linkedin.com/in/elisafinasiswanto/">Elisafina Siswanto</a> as the sharing session coordinator, for offering me this opportunity.</li><li>Thank you Pak <a href="https://www.linkedin.com/in/muhammad-adib-imtiyazi-b9b7a05a/">Muhammad Adib Imtiyazi</a> as my mentor, for suggesting and encouraging me.</li><li>Thank you <a href="https://www.linkedin.com/in/subhargh/">Maz</a> for helping and assisting me throughout the session.</li><li>Thank you Pak <a href="https://www.linkedin.com/in/boedybios/">Setia Budi</a> for motivating me to write this article.</li><li>Thank you DS &amp; MLE team for actively asking and discussing in my session.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c0787874ba22" width="1" height="1" alt=""><hr><p><a href="https://medium.com/tiket-com/being-a-speaker-as-an-intern-soft-introduction-to-vector-database-c0787874ba22">Being a Speaker “Soft Introduction to Vector Database” as an Intern</a> was originally published in <a href="https://medium.com/tiket-com">tiket.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Refleksi Dua Dekade: Menelisik Kembali Rencana dan Renjana]]></title>
            <link>https://khelli07.medium.com/refleksi-dua-dekade-menelisik-kembali-rencana-dan-renjana-3c8d91db0e7c?source=rss-e5fa95713910------2</link>
            <guid isPermaLink="false">https://medium.com/p/3c8d91db0e7c</guid>
            <category><![CDATA[storytelling]]></category>
            <category><![CDATA[journal]]></category>
            <category><![CDATA[reflections]]></category>
            <category><![CDATA[thoughts]]></category>
            <category><![CDATA[self-improvement]]></category>
            <dc:creator><![CDATA[Maria Khelli]]></dc:creator>
            <pubDate>Sat, 29 Oct 2022 17:07:29 GMT</pubDate>
            <atom:updated>2022-11-15T15:28:59.982Z</atom:updated>
            <content:encoded><![CDATA[<p>Kira-kira setahun yang lalu, saya membuat <a href="https://khelli07.medium.com/soal-mimpi-cita-cita-dan-idealisme-saya-sebagai-anak-19-tahun-2c6dcb7426bb">refleksi dan renungan saya saat umur 19 tahun.</a> Saya pikir ada baiknya untuk merenungkan kembali hal tersebut dengan pola pikir yang satu tahun lebih dewasa.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*XMqVWwHykoTFFczP" /><figcaption>Photo by <a href="https://unsplash.com/@ante_kante?utm_source=medium&amp;utm_medium=referral">Ante Hamersmit</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Tahun ini, genap dua dekade saya berkelana di dunia. Dengan kata lain, dekade ketiga saya baru saja dimulai. Namun, apakah itu berarti saya memasuki babak baru kehidupan? Ah, tidak juga. Seperti kata Pak Pram, “Baru, baru, baru, sampai orang dipaksa melupakan. Pada hakikatnya, kehidupan tetap sama, tetap yang kemarin juga.”</p><p>Jika kehidupan tetap yang kemarin, artinya tantangan akan terus datang — seperti yang sudah-sudah — dan kita harus siap berjuang untuk itu. Yang menjadi penting adalah bagaimana cara kita menghadapinya. Maka dari itu, saya pikir saya perlu berefleksi kembali soal apa yang saya harus lakukan (rencana) sehingga sejalan dengan apa yang saya senangi (renjana).</p><p><strong>Pengalaman menarik satu tahun terakhir ini</strong></p><p>Dalam satu tahun terakhir ini, terutama di awal tahun 2022, ada banyak sekali pengalaman yang saya dapatkan. Mulai dari <em>bootcamp</em>, magang di dua tempat yang berbeda, sampai kesempatan-kesempatan untuk berbicara dan berteman dengan orang-orang yang sudah berpengalaman. <em>I am exceptionally blessed!</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QciIpQJsfr6osxj7a2M6PA.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*A9mWCkpBgfTBol-SX_k0nQ.jpeg" /><figcaption>Sharing bersama Senior Researcher Google DeepMind (kiri) dan Software Engineer Google Japan (kanan)</figcaption></figure><p>Dari banyak pengalaman yang saya dapatkan, saya dipaksa berpikir dan berefleksi soal apa yang sebetulnya saya ingin lakukan dalam jangka panjang — kalau-kalau umur saya panjang. Saya juga dibuat sadar untuk belajar menyikapi hal-hal yang menyertai perjalanan saya ke depan. Sikap-sikap ini, setidaknya, cukuplah menjadi bekal saya untuk menghadapi kesulitan-kesulitan di masa yang akan datang.</p><p><strong>Saya harus bisa: belajar dengan sepenuh hati.</strong></p><p>Jika saya belajar dengan setengah hati, apa pun yang saya pelajari tidak akan ada gunanya. Tidak ada yang berkesan bagi saya. Maka dari itu, kadang-kadang saya harus memaksa diri saya untuk menyukai belajar hal tertentu agar apa yang saya pelajari bisa masuk ke dalam kepala. Kemampuan memaksa menyukai ini merupakan sesuatu yang tidak banyak orang punya.</p><p><strong>Saya harus bisa: bersikap rendah hati untuk belajar dari siapa pun.</strong></p><p>Saya perlu mengakui bahwa banyak sekali orang yang lebih baik dari saya. Tak terkecuali orang-orang yang saya (pernah) remehkan. Kadang-kadang, saya meremehkan orang lain, tetapi hal ini harus cepat-cepat saya sadari sehingga saya bisa mengoreksi diri saya. Saya harus sadar, mengakui orang lain lebih baik dan belajar dari mereka tidak akan mengurangi nilai-nilai yang saya miliki.</p><p><strong>Saya harus bisa: selalu penasaran untuk mencari tahu hal-hal yang saya tidak ketahui.</strong></p><p>Banyak sekali hal-hal menarik yang bisa digali ketika rasa penasaran terus muncul. Teman saya pernah bertanya seperti ini, “Bagaimana, sih, caramu membuat pertanyaan? Banyak pertanyaan bagusmu yang saya tidak terpikir sebelum kamu mengatakannya.” Saya hanya menjawab, “Pertanyaanku muncul karena penasaran.” Barangkali jawaban saya kurang memuaskan, tetapi itulah jawaban yang saya punya.</p><p>Tentunya poin-poin yang saya sebutkan di atas bisa jadi belum bisa saya praktikkan seratus persen, tetapi dengan menulis, saya terpaksa membuat janji atau kontrak kepada diri saya sendiri. Saya sadar, menulis memang gampang dan implementasinya selalu lebih sulit.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_ALUv8tBymGPYC62X_8UfQ.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jakLONfCeOYafe0yS2PYCQ.jpeg" /><figcaption>Saya berkunjung ke Kantor Garena (kiri) dan Kantor Ninja Van (kanan)</figcaption></figure><p><strong>Asa, renjana (<em>passion</em>), dan cita-cita</strong></p><p>Sebagai latar belakang, kesukaan saya selalu berubah-ubah. Mungkin saya mudah untuk menyukai hal-hal baru. Dulu SMP dan SMA, saya suka hal-hal abstrak seperti <a href="https://issuu.com/khelli07/docs/maria_khelli_portfolio">menggambar, mendesain, videografi, dan fotografi</a>. Lalu, saat kuliah, berubah 180 derajat ke hal-hal eksak seperti <a href="https://github.com/khelli07"><em>problem solving</em>, <em>data</em>, dan <em>software engineering</em></a>. Akhir-akhir ini malah tertarik juga soal sistem terdistribusi. Apa saya tidak makin bingung?</p><p>Jawabannya bisa iya, bisa juga tidak. Iya karena ada tendensi semakin banyak, semakin bingung. Tidak karena saya jadi punya kuasa untuk memilih. Itu anugerah yang diberikan oleh-Nya kepada saya. Toh, untuk karier, saya bisa memilih satu atau dua, sisanya saya bisa jadikan hobi saja. Maka dari itu, untuk sekarang, saya memilih <em>software engineering</em> dan sistem terdistribusi sebagai fokus utama, data sebagai sampingan (belajar karena penasaran), fotografi sebagai hobi.</p><p>Menentukan apa yang ingin dilakukan bukan berarti mimpi sudah terdefinisi seluruhnya, tetapi paling tidak cita-citanya sudah kian tergambar. Kalau bicara soal tujuan, saya akan blak-blakan menjawab tujuan saya adalah mencari uang. Namun, dari observasi saya, tujuan tersebut kurang berkelanjutan (<em>sustainable</em>) untuk jangka panjang. Akan ada saatnya tujuan tersebut ditinggalkan. Barangkali saja, saya di masa depan akan memilih untuk berkontribusi ke masyarakat melalui bidang ilmu keinformatikaan yang sedang saya tekuni sekarang.</p><p>Apa pun itu, harapannya adalah semoga saya terus memiliki semangat seperti yang saya miliki sekarang (atau lebih) sehingga kehidupan saya menjadi berguna bagi orang-orang di sekitar saya. Semoga demikian. Amin.</p><p>—</p><blockquote>“Kalau Anda dilahirkan dengan kelemahan, jangan mati tetap lemah. Manusia macam apa Anda? Anda didatangkan ke dunia untuk mati menjadi (seseorang yang) baik.”</blockquote><blockquote>— Pastor Eko Wahyu, OSC.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3c8d91db0e7c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Feedforward Neural Network (FNN) Implementation from Scratch Using Python]]></title>
            <link>https://khelli07.medium.com/feedforward-neural-network-fnn-implementation-from-scratch-using-python-467f51ecca3d?source=rss-e5fa95713910------2</link>
            <guid isPermaLink="false">https://medium.com/p/467f51ecca3d</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[neural-networks]]></category>
            <category><![CDATA[computer-science]]></category>
            <dc:creator><![CDATA[Maria Khelli]]></dc:creator>
            <pubDate>Fri, 17 Jun 2022 16:48:08 GMT</pubDate>
            <atom:updated>2023-07-28T04:54:42.572Z</atom:updated>
            <content:encoded><![CDATA[<p>Hi, if you are coming from the first part of the tutorial! If you are not, that’s totally OK too. Please kindly go through them first <a href="https://khelli07.medium.com/introduction-to-artificial-neural-network-in-deep-learning-aa7ba2280f50">here</a> where I explained the theory behind a neural network. I will also provide a quick review of the first part of the tutorial in this article. Oh, don’t forget to open your notes and code editor as we will get more mathematical and technical. Sit tight and let us start!</p><p><strong>Quick Review</strong></p><p>So, as you might have known, the process of a neural network consists of two processes: forward propagation and backward propagation. One forward pass and one backward pass are called an epoch. Hence, in each epoch, the network will update all of its weights and biases to minimize the cost (or loss) function — recall that our objective is to minimize the loss.</p><p>The flow of one epoch is such that</p><p>1. The inputs of several — possibly one — samples are fed into the network. Forward propagation is done when we have computed all the activation functions until the last or output layer.</p><p>2. From the last layer, we compute the loss using the cost function.</p><p>3. After that, we compute the error of the last layer, update its weights and biases, and continue to walk backward.</p><p>4. We walk backward by updating the weights and biases of the <em>l</em>-th layer using the error of (<em>l</em>+1)-th layer. Then, we stop at the first <strong>hidden</strong> layer since we will define the first layer as the input layer. Remember not to confuse the first layer and first <strong>hidden</strong> layer.</p><p>If you are still confused with the flow, I recommend you watch this <a href="https://www.youtube.com/watch?v=aircAruvnKk&amp;t=1024s">video</a>. If you are good, let’s continue. In the next sections, we will try to solve a simple regression task using a feedforward neural network. Before we start to code, I think we should plan the “attack” to tackle the problem.</p><p><strong>Plan of Attack</strong></p><p>We will define several things here, such as the architecture of the neural networks: how many layers we want in the network, how many neurons in each layer, what is the learning rate, and so forth.</p><p>Okay, so, I have made several decisions about the attack and I think it is pretty good — I’ve tested it. Here’s my plan:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LwhVZF9QfTT4QfR8qMIAbA.png" /><figcaption>Strategy sketch</figcaption></figure><p>Here, as you can see, we will use Rectified Linear Unit since our problem is a regression one. I will also take the learning rate as 0.0001 and ten thousand epochs.</p><p>Of course, you can try to design your plan, but I suggest you finish the tutorial first to see if your code works properly. Then, you can try to change the design here and there. Be careful in deciding them, though, as you might make your network broken (it does not learn anything)! In deep learning terms, I think it is called the vanishing gradient problem. It is when your weights and biases do not significantly change in learning, thereby making the loss keep at a constant value.</p><p><strong>Initial Setup: Data and Variables</strong></p><p>If you recount, from the first article I’ve defined some of the notation. We will use a similar notation here. That means we will use z, a, b, and w. However, I will give you an early notice since we will modify z’s formula from</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/238/1*L7Eiiyy0YWRm3XBYVOfT9w.png" /></figure><p>to</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/217/1*AvrcLAWUBUeNqVpZO5jOHQ.png" /></figure><p>because with this, we will minimize the computational load of transposing a matrix.</p><p>Now, let’s make a file named “lib.py” to store our cost and activation functions. We will make two functions for each type: one for the function itself (used in forward propagation) and one for its derivative (used in backward propagation).</p><p>I will start by defining it in mathematical form.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*efoj2pMC7614xb95nZKvFQ.png" /></figure><p>Then, in the Python file,</p><pre>import numpy as np</pre><pre># Activation<br>def RelU_forward(inputs):<br>    return np.maximum(0, inputs, dtype=np.float64)</pre><pre>def RelU_backward(inputs):<br>    return np.array(inputs &gt; 0, dtype=np.float64)</pre><pre># Cost<br>def cost_forward(ypred, ytrue):<br>    return 1 / 2 * (np.sum(np.square(ytrue - ypred)))</pre><pre>def cost_backward(ypred, ytrue):<br>    return ypred – ytrue</pre><p>After that, we will define our data. It will only be a simple linear line since we just want to simulate the network (you can try a quadratic line too if you want).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nZTBOs9QFK0D0BDlogLVwQ.png" /><figcaption>Example data</figcaption></figure><p>We make a new folder named “fnn.py” and then start by initializing some variables and parameters such that in our plan. Remember to put numpy seed to make the result consistent over time.</p><pre>import numpy as np<br>from lib import *</pre><pre>x = np.array([[1, 2, 3, 4],[5, 8, 2, 6]])<br>y = np.array([14, 25, 9, 23])  # 2x1 + 3x2 - 3<br>number_of_samples = len(x[0])<br>np.random.seed(0)</pre><pre>z = []<br>a = []<br>w = []<br>b = []</pre><pre>neurons = [2, 3, 2, 1]<br>number_of_layers = len(neurons) - 1<br>lr = 1e-4  # 0.0001 = 10^-4<br>epochs = 10000</pre><p><strong>Forward Propagation</strong></p><p>Now, we have ready to jump into the forward propagation part. If you have learned linear algebra, this part should be easy for you. Although most illustrations only take one input sample at a time, we will not. Since we only have 4 samples, it should be safe to feed them all to the network at once. Before that, I want to give you my sketch of the shape analysis I have done.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kgDxHLtklScG0OV6ZeuBbg.png" /><figcaption>Shape analysis</figcaption></figure><p>Don’t worry if you don’t get it. I just want to attach that here if any of you are curious. If you are more convenient to learn by printing the variables or creating breakpoints, you are welcome to do so.</p><p>Okay, now we will continue our code. In each layer, we will initialize our weights and biases first, then we compute z and a. Initialization technique can be random — it’s okay since we will update them in backpropagation. Here’s the code.</p><pre># FIRST HIDDEN LAYER<br>w.append(np.random.randn(neurons[1], neurons[0]))<br>b.append(np.ones((neurons[1], 1)))<br>z.append(w[0] @ x + b[0])<br>a.append(RelU_forward(z[0]))</pre><pre>assert a[0].shape == (neurons[1], number_of_samples)</pre><pre># SECOND HIDDEN LAYER<br>w.append(np.random.randn(neurons[2], neurons[1]))<br>b.append(np.ones((neurons[2], 1)))<br>z.append(w[1] @ a[0] + b[1])<br>a.append(RelU_forward(z[1]))</pre><pre>assert a[1].shape == (neurons[2], number_of_samples)</pre><pre># OUTPUT LAYER<br>w.append(np.random.randn(neurons[3], neurons[2]))<br>b.append(np.ones((neurons[3], 1)))<br>z.append(w[2] @ a[1] + b[2])<br>a.append(RelU_forward(z[2]))</pre><pre>assert a[2].shape == (neurons[3], number_of_samples)</pre><p>The <em>assert</em> lines do not really matter since they just serve as a checker. You can erase them if you want.</p><p>Yay, congratulations, you have done half epoch. Let’s move to a more challenging process: backward propagation. I believe you can do it too!</p><p><strong>Backward Propagation</strong></p><p>If you recall, I have given you 4 important equations in the first article. Basically, we will just implement those here. Let’s start from the last layer using this equation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/420/1*lLWEUEa47YpfKDYy4y68EQ.png" /></figure><p>The corresponding code is</p><pre># OUTPUT LAYER<br>delta = cost_backward(a[2][0], y) * RelU_backward(z[2])</pre><p>Since we have the delta, we will also update our weights and bias of the last layer. This means we are also implementing gradient descent using these equations. The derivatives are</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/634/1*pT0FVBh3ukEMLNeGtHvk3w.png" /></figure><p>and we update using</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/553/1*Dujvz8UZ8C-lGp57Po8HDg.png" /></figure><p>Respectively, the code is</p><pre>w[2] = w[2] — lr * (delta @ a[1].T)<br>b[2] = b[2] — lr * (delta)</pre><p>After that, we will move one step backward, updating our second hidden layer. To compute the layer’s delta, we will use this equation this time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/661/1*QOROgeoASc5diBGrhYuDBA.png" /></figure><p>Be cautious on the transpose in the weight term. This time, we will need them, otherwise, we will have shape dimension conflict. Here’s the code for computing error and optimization for the second hidden layer.</p><pre># SECOND HIDDEN LAYER<br>delta = (w[2].T @ delta) * RelU_backward(z[1])<br>w[1] = w[1] - lr * (delta @ a[0].T)<br>b[1] = b[1] - lr * (delta)</pre><p>The same will be applied to the first hidden layer. But, the difference is in the activation of the (<em>l</em>-1)th layer (see dC/dW). You will use the input samples x (when you are updating weights) since you don’t have a[-1]. Thus, the code is</p><pre>#  FIRST HIDDEN LAYER<br>delta = (w[1].T @ delta) * RelU_backward(z[0])<br>w[0] = w[0] - lr * (delta @ x.T)<br>b[0] = b[0] - lr * (delta)</pre><p>Kudos, you just finished one epoch! You deserve yourself a pat on the back. I’m proud of you! Now your networks are a little bit better than last time. If you want to see the progression, you can print the loss of the network epoch after epoch. Oh, I have not told you how to loop the epoch, haven’t I? Here’s it.</p><pre>for i in range(1, epochs):<br>    # Forward propagation<br>    for j in range(number_of_layers):<br>        if j == 0:<br>            z[j] = w[j] @ x + b[j]<br>        else:<br>            z[j] = w[j] @ a[j - 1] + b[j]</pre><pre>        a[j] = RelU_forward(z[j])</pre><pre>     print(f&quot;Epoch ({i + 1}/{epochs}), loss = {cost_forward(a[2], y)}&quot;)</pre><pre>    # Backward propagation<br>    for j in range(number_of_layers - 1, -1, -1):<br>        if j == number_of_layers - 1:<br>            delta = cost_backward(a[j][0], y) * RelU_backward(z[j])<br>        else:<br>            delta = (w[j + 1].T @ delta) * RelU_backward(z[j])</pre><pre>        if j == 0:<br>            w[j] = w[j] - lr * (delta @ x.T)<br>        else:<br>            w[j] = w[j] - lr * (delta @ a[j - 1].T)</pre><pre>        b[j] = b[j] - lr * (delta)</pre><p>Now your code is fully functional. You should expect this on your console if you run “fnn.py”.</p><pre>Epoch (10000/10000), loss = 0.00030291977689243294<br>last y_train predicted (a[2]) = [[14.02074786 24.98681486  8.99915625 23.001178  ]]</pre><p>It is actually pretty good, huh? Of course, this is not a realistic scenario since we do not split our data to train and test, thereby making our model prone to overfitting. But, that’s okay. The purpose of this tutorial is to give you the mathematical headache behind neural networks, haha!</p><p><strong>Code Summary</strong></p><p>Here, I will provide you with 3 versions of the code. The <a href="https://github.com/khelli07/ai-fnn/blob/main/src/fnn_no_oop/fnn.py">redundant one</a> (the one we use in the tutorial above) and the <a href="https://github.com/khelli07/ai-fnn/blob/main/src/fnn_no_oop/fnn_concise.py">concise one</a>. I have also tried to make it more modular <a href="https://github.com/khelli07/ai-fnn/tree/main/src/nn">here</a>.</p><p>That’s all for this feedforward neural network tutorial. I hope that helps you. As usual, if you see any concept or typing mistake, please don’t hesitate to let me know. If you are still keen to learn, you can try to implement these codes in object-oriented programming, like the one in those famous libraries. Thank you for visiting and happy learning!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=467f51ecca3d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introduction to Artificial Neural Network in Deep Learning]]></title>
            <link>https://khelli07.medium.com/introduction-to-artificial-neural-network-in-deep-learning-aa7ba2280f50?source=rss-e5fa95713910------2</link>
            <guid isPermaLink="false">https://medium.com/p/aa7ba2280f50</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[neural-networks]]></category>
            <category><![CDATA[computer-science]]></category>
            <dc:creator><![CDATA[Maria Khelli]]></dc:creator>
            <pubDate>Tue, 14 Jun 2022 13:39:15 GMT</pubDate>
            <atom:updated>2022-06-17T16:49:38.620Z</atom:updated>
            <content:encoded><![CDATA[<p>Take a look at the handwritten digit picture below. The picture was taken from the <a href="https://www.tensorflow.org/datasets/catalog/mnist">TensorFlow dataset catalog</a> named MNIST.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/241/1*I5i7pF9Qnt8sRv2Q8jk9tg.png" /><figcaption>Preview of MNIST dataset</figcaption></figure><p>It is easy for us to recognize that the numbers are 4, 1, and 0. That just shows how magnificent our brain is. We can recognize the digit almost effortlessly. However, when we try to make computers recognize these images, it becomes a complicated task.</p><p>You might think that you can make a program that recognizes the digit using a rule-based algorithm. For instance, the number zero comes in a full circle. But, then, you realize that not all people have decent handwriting, so you start defining your rule all over again. Before you realize it, your code is already 500 lines long. Oh, crap!</p><p>Afraid not, this sophisticated study called deep learning has made digit recognition much easier. Even more fascinating, its ability is not limited to recognizing handwriting, but they are now used in autonomous driving cars. You might not realize it, but deep learning and artificial intelligence (AI) are already implemented in every aspect of our lives: healthcare, education, and even social media.</p><p>The recommendation that pops on your YouTube home page is implemented using AI. Machine translation and search engines such as Google Translate and Google Search are also implemented using AI. The difference is the field of study. So, if you are interested in YouTube’s recommendation algorithm, you should deep learn that field (pun intended). Likewise, if you are interested to make computers understand human languages, narrow down on NLP. I believe you have already known most of those facts since you clicked this article. Hence, without further adieu, let’s start!</p><p>So, what is deep learning? Deep learning is a subset of machine learning (ML) and ML is a subset of AI. The main character of deep learning algorithms is the neural network. The simplest neural network is a feedforward neural network (FNN) and that will be our main topic of this tutorial.</p><p>I will split this tutorial into two parts: an introduction to the terms and theories behind FNN and implementation of FNN with Python (from scratch, with no external library except NumPy). I will try to provide two versions of the implementations: one without object-oriented programming and one with.</p><p>Before going on further, I want to warn you that some linear algebra will be involved (especially in the second part). So, if you find any difficulties, please try to learn or review linear algebra. I will provide a reference <a href="https://www.deeplearningbook.org/contents/linear_algebra.html">here</a>.</p><p><strong>Neural Network: Brief Introduction</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/906/1*1qUtF2x5ClH8Yfr6B0z0uQ.png" /><figcaption>Neural network</figcaption></figure><p>A neural network usually consists of several layers in which each layer has several neurons. In a fully connected neural network, like a feedforward neural network, each neuron is connected. Each layer has its own “task” to recognize the inputs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/961/1*L5D73u4SYnA_JZM4R4Q-3A.png" /><figcaption>Illustration of how neural network learns</figcaption></figure><p>As we can see, the picture tells us how the neural network works. The first <strong>hidden</strong> layer tries to recognize the lines of the face, the second hidden layer tries to identify the features of the face, and the last layer tries to see the whole view of the face. This is <strong>roughly</strong> how the neural network learns. Hence, that does not mean you must have exactly three layers to recognize images. It can be less than three; it can be more than that. I believe you get the idea. Generally, neural networks learn better with more layers and neurons since they have more parameters, but computational tradeoff should be considered.</p><p><strong>Perceptrons: Forward Propagation</strong></p><p>Let us start with the concept of a perceptron. Basically, a perceptron is just a neural network that consists of one hidden layer with one neuron.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hy-AWK9JKS8oFjfZzGESHQ.png" /><figcaption>The perceptron</figcaption></figure><p>The perceptron takes several inputs, gives weights to them, and processes them in a nonlinear activation function. The activation function used depends on the task you are going to achieve. If the task is a binary classification, we normally use the sigmoid activation function — since it ranges from 0 to 1. If the task is a regression one, we can use the rectified linear unit (ReLU). There are other activation functions such as tanh and softmax. You can try to mix the activation function in each layer. For instance, the first hidden layer with ReLU and the output layer with the sigmoid. Whatever suits your task.</p><p>To compute the output of perceptron, we use the equation</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/304/1*7STSEs39zDgXtxjZnYyq-w.png" /></figure><p>where g is the activation function and b is the bias (same as w_0). It can be vectorized such that</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/231/1*QoTIt2dLSS-NnVbkHEWEJg.png" /></figure><p>and</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/195/1*uS28Ycf_dkxB5aBp5TEyyQ.png" /></figure><p>For one sample input. This vectorization will help us to speed up computation. Thus, for-loop iteration is not needed.</p><p>So, now you get the idea of how a perceptron works. Now, going back to the feedforward neural network.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/895/1*CPDTLTrakGGa61AnOirMDg.png" /></figure><p>The way it works is just like the perceptron. Hence, the computation of a_1(2) — sorry, Medium does not really support equation notation — is</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/876/1*ruxUrtdeRBUtZCyWnyU-Lw.png" /></figure><p>To read the notation, a_j(l) is the activation result of neuron j in layer l. The readings are the same for z and b. But, for the weight, w_ij(l) would mean the weight that connects neuron <em>j </em>in (<em>l</em> — 1)th layer to the neuron <em>i</em> in <em>l</em>-th layer. This computation will carry on to the next layer, such that to compute a_1(3), we do</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/859/1*bMBsW17rxQMyb4MUW5N0Xw.png" /></figure><p>Thus, the y_hat or the prediction is the output of the last layer, i. e. a_1(3).</p><p>With this, you can start computing the cost function. The most commonly used cost function is the sum of squared error (SSE). The choice of cost function might depend on your task (regression or classification), but SSE can be used for both.</p><p><strong>Backward Propagation</strong></p><p>Now, arguably the most difficult part of a neural network is backward propagation. This is the part where the network learns by updating all of its weights and biases. There are several techniques for optimizing the weights and biases, such as gradient descent, normal equation, and adaptive moment estimation (Adam). But, in this article, we will mainly discuss gradient descent.</p><p>So, how do we know that a neural network is good enough? Its cost function should be minimum. If you recall the calculus you have learned in high school, you can use derivatives to minimize a function. Thus, we will update the weights and biases of the networks by using the derivative of the cost function with respect to its weights and biases respectively. We will start walking backward — hence called backward propagation — from the output layer to the first hidden layer.</p><p>According to Nielsen (Neural Networks and Deep Learning), there are four important equations for backward propagation. The concept of chain rule will play an important role in every equation. Notice that every equation is in its vectorized form.</p><p>The first one is the error from the output layer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/291/1*OUvL8eZd9PnbkObgbNnLsA.png" /></figure><p>where the delta is the error of j-th output of the last layer (L). Then, for all the hidden layers, the error in terms of the next layer’s error is</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/471/1*pPndxT0iU3pV3pOJLzPIuQ.png" /></figure><p>where the O with a dot is the symbol of Hadamard product, i. e. elementwise multiplication. Next, The last two will be crucial components in updating the weights and biases.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/342/1*_mXPFjR0a4oPOc_o48vFAA.png" /></figure><p>After we got the result of the last two equations, we update the weights and biases by using</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/514/1*Quu4LkRg8LU_YB55ox_EXw.png" /></figure><p>where eta is the learning rate. It should be chosen carefully. If you pick the number too small, your network is going to learn slowly, but if you pick the number too high, your network might move further away from the minimum.</p><p>Now you know the four equations that are used in backward propagation. We will try to implement these in part two of the tutorial. For now, I want to give you a visualization of how the gradient descent work.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/730/1*k-o0ae7Oo3hohiH6FHtFqQ.png" /></figure><p>You can think of gradient descent works by moving down toward the minimum cost function just like a ball rolling down through a hill. It is unlike what you may have seen in your high school where the derivatives equal to zero — think of it as teleporting the ball to the valley. That teleporting technique is called a normal equation (you can try to Google it). The advantage of using a normal equation is that it needs no learning rate nor iteration to achieve a minimum cost function. But, they are not feasible if the problem is too complex and the number of variables is too high.</p><p><strong>Neural Network: Conclusion</strong></p><p>As we have discussed before, a neural network consists of two processes: forward propagation and backward propagation. In the forward propagation, inputs are computed and processed to produce output(s). From then, the loss is computed using the cost function. Recall that the goal of a neural network is to minimize this cost function. Hence, the derivative of its cost function is computed and propagated back to update the weights and biases.</p><p>The main idea of most neural networks is the same. Even if it is a simple neural network (or FNN), convolutional neural network (CNN), or recurrent neural network (RNN). They all have two processes: forward propagation and backward propagation. The difference in how each network is processed is in its forward or backward propagation. Hence, the neuron composition might differ. One example would be that single long short-term memory (LSTM) neuron — or cell — has an input gate, forget gate, and output gate which a simple artificial neuron does not have.</p><p>I think that’s all for the introduction. Congratulations on finishing this reading. I hope my writing is understandable. If you notice any mistake in my writing — whether it is a concept or typo — please let me know.</p><p>Next step: <a href="https://khelli07.medium.com/feedforward-neural-network-fnn-implementation-from-scratch-using-python-467f51ecca3d">Feedforward Neural Network (FNN) Implementation from Scratch Using Python</a>.</p><p><strong>References</strong></p><p>Amini, Alexander. 2022. <a href="https://www.youtube.com/watch?v=7sB052Pz0sQ&amp;t=408s">MIT Introduction to Deep Learning | 6.S191</a>.</p><p>Mahaprata, Sambit. 2018. <a href="https://towardsdatascience.com/why-deep-learning-is-needed-over-traditional-machine-learning-1b6a99177063">Why Deep Learning over Traditional Machine Learning</a>.</p><p>Nielsen, Michael. 2019. <a href="http://neuralnetworksanddeeplearning.com/">Neural Networks and Machine Learning</a>.</p><p>Ognjanovski, Gavril. 2019. <a href="https://towardsdatascience.com/everything-you-need-to-know-about-neural-networks-and-backpropagation-machine-learning-made-easy-e5285bc2be3a">Everything you need to know about Neural Networks and Backpropagation — Machine Learning Easy and Fun</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aa7ba2280f50" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Managing Time with CPU Real-Time Scheduling Algorithm]]></title>
            <link>https://khelli07.medium.com/managing-time-with-cpu-real-time-scheduling-algorithm-ab2367de7d65?source=rss-e5fa95713910------2</link>
            <guid isPermaLink="false">https://medium.com/p/ab2367de7d65</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[scheduling]]></category>
            <category><![CDATA[time-management]]></category>
            <category><![CDATA[algorithms]]></category>
            <category><![CDATA[cpu]]></category>
            <dc:creator><![CDATA[Maria Khelli]]></dc:creator>
            <pubDate>Sat, 26 Mar 2022 05:04:43 GMT</pubDate>
            <atom:updated>2022-04-01T15:33:18.465Z</atom:updated>
            <content:encoded><![CDATA[<p>“If only I had more time, I am sure that I can spend it with you,” said Luke to his girlfriend, Sarah. “No, we all have the same amount of time. It is just you who did not make your time for me!” Sarah replied. Luke froze and no words came out of his mouth. His empty eyes watching Sarah went away, drowning him in regrets.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ELHESqTcdPSpPYhl" /><figcaption>Photo by <a href="https://unsplash.com/@dariusbashar?utm_source=medium&amp;utm_medium=referral">Darius Bashar</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Don’t we all have the same problem as Luke? No, not the girlfriend or boyfriend thing, but the time management one. I believe we all have experienced difficulties in managing time. This may or may not leave us with consequences and regrets later on. But, do you know that computers also need to effectively manage their time?</p><p>Before going on, let me explain some of the terms and basic concepts in operating systems. In utilizing resources, computer scientists have an objective called multiprogramming. The multiprogramming means that the CPU needs to have some process to execute most of the time (it should not be chilling!).</p><p>The idea of multiprogramming is simple. If a process needs to wait for some external requests (e.g I/O request), the CPU will suspend the process, and put it in the waiting queue until it is ready again. But, while waiting, the CPU will execute another process in the ready queue. Hence, the CPU will not be sitting idle, waiting indefinitely for I/O from another party.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*JmA00zBiQPn3Wfsg" /><figcaption>Photo by <a href="https://unsplash.com/@brostvarta?utm_source=medium&amp;utm_medium=referral">Francesco Vantini</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>The concept is basically the same for us. <strong>We will take this analogy: CPU as us, the person, and processes are our tasks</strong>. When we want to finish all of our assignments, we utilize our energy, skills, and time as much as we can. We can try to maximize this by using a CPU scheduling algorithm.</p><p>There are a lot of CPU scheduling algorithms, but this algorithm is the one that is working for me lately. It is intuitive, though. The algorithm is taken from real-time CPU scheduling called Earliest-Deadline-First (EDF). From its name, you can guess how it works, don’t you?</p><p>EDF scheduling assigns priorities dynamically according to the deadline and time to finish the process. The earlier the deadline, the faster you should execute it. However, when two or more processes have the same deadlines, do which one with the shortest time to finish. Furthermore, if both the deadlines and time to finish are the same, pick using FCFS (first come, first served) algorithm. In the real-world case, you can add your own priority criteria to your processes.</p><p>Note that the EDF algorithm is preemptive. When a new process comes with higher priority, you should stop whatever you are doing right now and start executing the new process.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2D8X1VJ3Qt6YQqxW" /><figcaption>Photo by <a href="https://unsplash.com/@villxsmil?utm_source=medium&amp;utm_medium=referral">Luis Villasmil</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Theoretically, the EDF scheduling algorithm is very efficient, compared to other real-time scheduling algorithms. That being said, we do not have energy all the time, don’t we? Therefore, we may need to stop processing one task, take a break, and start another one (in CPU, it can be called context switching). Hence, 100% efficiency in the EDF algorithm is hard to achieve in practice since it is less predictable — we never plan to run out of energy, right?</p><p>However, afraid not, since we still can achieve relatively high efficiency in utilizing our resources. My advice is to add some modifications to your algorithm. For instance, when a task is impossible to finish before the deadline, leave it alone and move on to another one. This will avoid the unwanted domino effect (when all processes miss their deadlines).</p><p>Let us go back to Luke’s problem. From my explanation, it seems that he can try to fix his time management by implementing the EDF algorithm in his scheduling. Even so, he needs to add his own priority criteria, though! Luke can give higher priority to the things he finds important. I am sure he will be able to make time for his future wife. ;)</p><p>Good luck to Luke and us! May we find a way to spend our time wisely. It is not about doing a lot of (unnecessary) jobs. But, it is about doing whatever is important to us, whether it is family, girlfriend/boyfriend, or yourself.</p><p>References: Silberschatz, A., Galvin, P. B., &amp; Gagne, G. (2018). <em>Operating System Concepts 10th edition</em>. Hoboken, NJ: Wiley.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ab2367de7d65" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Overcoming Fear and Regrets: How I Make Decisions]]></title>
            <link>https://khelli07.medium.com/overcoming-fear-and-regrets-how-i-make-decisions-b5804206c0b2?source=rss-e5fa95713910------2</link>
            <guid isPermaLink="false">https://medium.com/p/b5804206c0b2</guid>
            <category><![CDATA[failure]]></category>
            <category><![CDATA[regret]]></category>
            <category><![CDATA[dreams]]></category>
            <category><![CDATA[decision-making]]></category>
            <category><![CDATA[fear]]></category>
            <dc:creator><![CDATA[Maria Khelli]]></dc:creator>
            <pubDate>Sat, 19 Mar 2022 04:58:59 GMT</pubDate>
            <atom:updated>2022-03-25T03:35:33.334Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_oLRK_DrNFZuJNQu" /><figcaption>Photo by <a href="https://unsplash.com/@zymot?utm_source=medium&amp;utm_medium=referral">Joao Luis</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><blockquote><em>“With great power comes great responsibility.” — Uncle Ben</em></blockquote><p>Have you ever wondered what power does Uncle Ben mean? Is it some political power? What about physical power? or even computing power?</p><p>All of that <em>might be</em> true, but in my perspective, it all comes down to <strong>the power of making decisions.</strong> Why? Because we make decisions in everything. We decide what political party we want to vote for. We decide whether or not we want to work. Computer scientists also decide what algorithm they use.</p><p>For every decision, comes great responsibility. It is for us to take any consequences that will or will not happen based on decisions we made. Hence, the fear of failure may haunt you overnight and leave you overthinking — at least it is for me.</p><p>In making everyday decisions, the fear of failure will not likely surface. They have become automatic. However, if it is a life-changing decision, it is harder for us to choose the alternatives. But, I will tell you that making no decision is itself a decision. You decide that you did not choose anything.</p><p>Ruth Chang, in her TEDTalks, <a href="https://www.youtube.com/watch?v=8GQZuzIdeQQ"><em>How to Make Hard Choices</em></a>, defines the difference between easy choices and hard choices. She said,</p><p>“In an easy choice, <strong>one alternative is better than the other</strong>. Whereas in a hard choice, one alternative is better in some ways, and the other alternative is better in some other ways. But, overall, <strong>neither of these is a better overall</strong>.”</p><p>When you think about it, the one you think is a hard choice might be the easy one. Let me give you an example. Suppose that you have a chance — even a little — to be accepted as a student in your dream university. However, in the process of application, there are many stages that you are <em>not comfortable</em> doing. For instance, public speaking, debate, or an interview. Then, should you continue to apply?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YHjPkMPbHMastz4C" /><figcaption>Photo by <a href="https://unsplash.com/@franku84?utm_source=medium&amp;utm_medium=referral">Vadim Bogulov</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>As a person who has gone through the example I mentioned before, I also experience the same fear. I am ashamed if anything I said was wrong. I am afraid that things did not go as planned. I regret when I failed the application. But, the question is, if you did not go for it, does it mean that you will have no regret?</p><p>If you did not take the chance, you are failing for yourself. You did not fail because your skills are not eligible, but you fail because you choose to. You decide to fail. So, <strong>it is clear</strong> that it is an easy choice: to attempt it.</p><p>We are afraid because it is outside of our comfort zone<strong>.</strong> Therefore, instead of being uncomfortable when going through all the processes, we choose to let it go.<strong> It isn’t because not trying is better than trying.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*F7UWy4MZaE2vqgM9" /><figcaption>Photo by <a href="https://unsplash.com/@24ameer?utm_source=medium&amp;utm_medium=referral">Ameer Basheer</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><blockquote>“Perfection prevents action.” — Simon R. Covey</blockquote><p>For me, the regret of not trying is more painful — it lingers longer — than trying but failing. Life is not all about success. Yes, success is good, but we don’t have to be perfect, to be successful all the time. We will eventually fail, though. As for myself, life is about learning, including learning to make better decisions.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b5804206c0b2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Soal Mimpi, Cita-Cita, dan Idealisme Saya sebagai Anak 19 Tahun]]></title>
            <link>https://khelli07.medium.com/soal-mimpi-cita-cita-dan-idealisme-saya-sebagai-anak-19-tahun-2c6dcb7426bb?source=rss-e5fa95713910------2</link>
            <guid isPermaLink="false">https://medium.com/p/2c6dcb7426bb</guid>
            <dc:creator><![CDATA[Maria Khelli]]></dc:creator>
            <pubDate>Tue, 13 Jul 2021 12:30:11 GMT</pubDate>
            <atom:updated>2022-08-08T14:19:09.648Z</atom:updated>
            <content:encoded><![CDATA[<p>Di umur saya yang hampir 19 ini, apa <em>sih </em>yang saya ketahui? Saya masih anak kemarin sore. Pengalaman hidup juga belum banyak, kerjaannya kebanyakan main dan belajar. Asin dan pahitnya kehidupan pun baru terasa sedikit. Karena saya belum mengetahui banyak hal, apa saya harus punya mimpi dan cita-cita yang spesifik? Toh, saya juga tidak tahu apakah mimpi dan cita-cita saya tepat untuk saya sendiri.</p><p>…</p><p>Bicara soal mimpi dan kesuksesan, saya yakin setiap orang punya definisinya masing-masing. Bisa sederhana, juga bisa kompleks. Beberapa orang mengatakan bahwa mereka tak punya mimpi atau cita-cita. Saya rasa tidak. Mereka punya, tetapi belum sadar — masih berjuang menyadari — atau belum bisa mendefinisikannya dengan kata-kata. Jika sesungguhnya mereka memang tak punya, lantas mengapa mereka masih mencoba bertahan tanpa tujuan?</p><p>Memang, perlu renungan mendalam atas hal itu, tetapi menurut saya, jika memang merasa belum punya, lakukan saja apa pun yang membuat kita senang. Pasti ada.</p><p>“Betapa sederhana hidup ini sesungguhnya. Yang pelik cuma liku dan tafsirannya,” begitu kata Pak Pramoedya A.T. dalam <em>Rumah Kaca</em>. Saya rasa, saya setuju dengan perkataan beliau. Manusia terlalu membuat kompleks segala sesuatu, padahal apa yang dipikirkannya juga belum terjadi — orang bilang ini <em>overthinking</em>. Pun saya tak bisa mungkiri bahwa terkadang saya juga demikian, dan itu manusiawi. Syukur, masih berpikir menandakan kita masih hidup dan berusaha hidup, setidaknya itu sisi positifnya.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*T7CiVGw7ga-4wgsT" /><figcaption>Photo by <a href="https://unsplash.com/@heytowner?utm_source=medium&amp;utm_medium=referral">JOHN TOWNER</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><strong>Jalan Hidup dan Kesempatan setiap Orang Berbeda-beda</strong></p><p>“Setiap orang punya jalan hidupnya masing-masing,” kata kebanyakan orang. Betul, maka kita tak dapat berharap bahwa jalan yang kita tempuh memiliki tingkat kesulitan yang sama dengan jalan orang lain.</p><p>Kadang-kadang, saya merasa kurang bersyukur. Melihat kuli-kuli pasar, penjual makanan gerobak, penyanyi dangdut keliling, atau mereka — yang menurut pandangan saya — kekurangan. Mereka justru mampu merasa senang dan cukup atas apa yang mereka miliki.</p><p>Saya malu. Mungkin saya hidup dalam cita-cita finansial mereka. Mungkin saya hidup dalam mimpi mereka yang tidak pernah duduk di atas bangku sekolah. Mungkin saya hidup dalam idealisme mereka, yang mungkin telah hilang. Saya malu karena beberapa kali, secara sengaja maupun tidak, menyia-nyiakan kesempatan yang saya miliki.</p><p>Pernah sewaktu-waktu saya merasa lelah berjuang dan merasa ingin hidup seperti beberapa teman saya —yang menurut pandangan saya— tidak terlalu punya idealisme yang tinggi. Kemudian, saya “ditampar” dengan perkataan Pak Eko, Guru SMA saya, “Kamu itu ingin jadi orang lain, padahal mungkin orang lain ingin yang jadi seperti kamu.”</p><p>Dan kemudian saya menyadari, saya punya kekuatan yang tak orang lain miliki.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*RCxd6X86O7JXOTgu" /><figcaption>Photo by <a href="https://unsplash.com/@stijnswinnen?utm_source=medium&amp;utm_medium=referral">Stijn Swinnen</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><strong>Kekuatan, Mimpi, dan Cita-Cita</strong></p><p>Saya sendiri mempunyai daya juang dan idealisme yang tinggi. Apa yang saya inginkan akan saya rencanakan dan akan saya laksanakan dengan sekuat tenaga dan usaha yang saya miliki. Buruknya, terkadang saya tertutupi oleh kacamata kuda — hanya berorientasi target, tanpa menghargai proses yang saya jalani sehingga terkadang merasa usaha saya sia-sia. Namun, saya semakin belajar untuk menghargai dan menikmati proses yang saya lalui.</p><p>Bagaimana dengan cita-cita dan mimpi? Saya tidak yakin saya punya. Mimpi dan cita-cita saya sama abstraknya dengan kebanyakan orang: menjadi sukses dan bebas secara finansial. Namun, muncul pertanyaan baru, sukses yang bagaimana? Bebas finansial yang bagaimana? Setiap perjalanan ada ujung, bukan?</p><p>Meski demikian, terlepas dari itu, saya yakin setidaknya saya punya alasan untuk terus berusaha berjuang. Saya punya hal-hal yang disenangi, saya punya orang-orang yang disayangi. Bisa jadi juga, dengan usaha dan jasa saya, banyak orang akan terbantu. Saya percaya setiap orang punya perannya masing-masing di dunia ini. Saya juga percaya setiap orang punya anugerah yang tidak layak untuk disia-siakan.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*R9f6Ulm8b7AUAdRx" /><figcaption>Photo by <a href="https://unsplash.com/@punttim?utm_source=medium&amp;utm_medium=referral">Tim Gouw</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><strong>Hidup untuk Mencari Tantangan dan Berjuang Melewatinya</strong></p><p>Ada dua kalimat dari Pak Didik, Guru SMA saya, “Hidup ini untuk mencari masalah, bukan? Dengan menyelesaikan masalah itu, kita mendapat kebahagiaan.” Perkataannya benar, maka saya berusaha menantang diri saya untuk menjadi lebih baik.</p><p>Kegagalan juga saya artikan sebagai masalah dan satu-satunya penyelesaian masalah itu adalah bangkit darinya. Memang tak mudah, pun saya juga masih harus banyak belajar mengikhlaskan hal-hal yang di luar kuasa saya. Saya harus bisa belajar dari kegagalan saya.</p><p>Pada akhirnya, hidup adalah soal <strong>memperjuangkan</strong> dan <strong>diperjuangkan</strong>. Masih banyak misteri dan pertanyaan hidup yang belum terpecahkan. Saya akan terus <strong>berjuang</strong> mencarinya. Saya tidak ingin menyia-nyiakan waktu yang saya miliki. Semangat selalu, selamat berjuang, semuanya!</p><p>…</p><p>“Jarum (jam) itu kembali ke titik nol lagi, tetapi waktu berputar dan tak akan pernah kembali lagi.”</p><p>— Pak Kasdi, Guru SMA saya (lagi).</p><p><strong>p.s.</strong> guru SMA saya keren-keren :D</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2c6dcb7426bb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[2020: A Year of Catastrophe, But Not for Me]]></title>
            <link>https://khelli07.medium.com/2020-a-year-of-catastrophe-but-not-for-me-51ac51c4ae17?source=rss-e5fa95713910------2</link>
            <guid isPermaLink="false">https://medium.com/p/51ac51c4ae17</guid>
            <category><![CDATA[regret]]></category>
            <category><![CDATA[experience]]></category>
            <category><![CDATA[love]]></category>
            <category><![CDATA[self-improvement]]></category>
            <category><![CDATA[gratitude]]></category>
            <dc:creator><![CDATA[Maria Khelli]]></dc:creator>
            <pubDate>Wed, 20 Jan 2021 14:15:48 GMT</pubDate>
            <atom:updated>2022-05-14T03:36:10.323Z</atom:updated>
            <content:encoded><![CDATA[<p>See positively, learn positively, and a year of a pandemic is not bad either.</p><p>As I scrolled down through my Instagram weeks ago, I saw many people grumbling that 2020 is the worst year ever. Covid-19 has taken away everything: we can’t hug our dearest; we can’t visit our closest; and the safest way to have a holiday is to be at home — which many people find boring.</p><p>Nevertheless, I found a lot of “best of the best” experiences in 2020. I learned and realized many things that weren’t coming in the previous years. There are at least three things I took from 2020.</p><h3><strong>Be grateful for every person that has stayed with you no matter how hard the situation is</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*m9bsuwH5gcLSk8bS" /><figcaption>Photo by <a href="https://unsplash.com/@kylo8?utm_source=medium&amp;utm_medium=referral">Kylo</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Most of us realize that university is a stepping stone to a better future, including myself. Though I also believe that success comes from yourself, not others, I find it necessary to have good connections and relations — which you can find in universities. That motivated me to enroll in a good university in Singapore.</p><p>It was about March 2020 when the announcement struck me. It broke my heart into pieces. I had worked and prayed hard for hours, asked everybody how I was doing, and thought about what I could do better to get into that university. However, God has another plan for me. I was not destined to be there, yet.</p><p>I was afraid that I disappointed my beloved ones, but I was mistaken. They do not blame me nor are disappointed in me. Instead, they encourage me to rise up and come back stronger.</p><p>There, at that moment, I saw things that I had never seen before. It made me grateful for all people that had chosen to stay, that had embraced me, and that had loved me even in my darkest moment.</p><h3><strong>Work hard, study hard, and pray harder</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*SaVSqLAqPNCBBTRY" /><figcaption>Photo by <a href="https://unsplash.com/@mariogogh?utm_source=medium&amp;utm_medium=referral">Mario Gogh</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Everyone has their definition of success. For me, it is to make my beloved ones proud of me. To achieve that, I must not give up at any cost.</p><p>Moving on to August 2020, I was accepted at one of the best universities in Indonesia. My dearest, including my parents and sisters, were proud and glad to hear the acceptance. It made me understand that God has a better plan than mine.</p><p>Here, I find many incredible people with a bunch of achievements. That motivates me to do better and to be the best version of myself. Work hard, study hard, and pray hard. The best is yet to come.</p><h3><strong>Learn from the mistake, but do not regret it</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*a7CyeIEy95ulYiW3" /><figcaption>Photo by <a href="https://unsplash.com/@walre037?utm_source=medium&amp;utm_medium=referral">Rémi Walle</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>2020 is a year of a roller coaster for me. I lost one of my closest friends because of my negligence.</p><p>Imagine losing someone you dear so much, but only having a little hope for them to come back. Every memory that comes back every night has undoubtedly stabbed my heart over and over again. They had been very close to me, had gone through a lot with me, and had tears and laughs together. Yet, I was not able to talk and apologize properly because of the pandemic.</p><p>It was about the end of November 2020 when that happened. At first, I did regret and blamed myself for doing such a thing, but then I realized that humans are learners. We learn when we make mistakes, so never regret when you did them. Everything comes and goes for a reason, welcome them and let them go.</p><p>Of everything that happens in 2020, be grateful and don’t regret it. More importantly, as Javanese philosophy says, “Urip iku urup,” — that our life should be a “light” to others — that’s how we should live our life.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=51ac51c4ae17" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>