用Python構建個性化智能鬧鐘

人工智能遇見磐創 發佈 2020-08-10T03:20:57+00:00

你可能之前有見過有人使用Python語言構建鬧鐘,幫助他喚醒或提醒他一個重要的會議。這些都是很簡單,沒有任何智能,他們所做的只是播放你設置的鬧鐘音樂,或者隨機選擇一個YouTube視頻或歌曲來播放。

你可能之前有見過有人使用Python語言構建鬧鐘,幫助他喚醒或提醒他一個重要的會議。

這些都是很簡單,沒有任何智能,他們所做的只是播放你設置的鬧鐘音樂,或者隨機選擇一個YouTube視頻或歌曲來播放。

所以,讓我們更上一層樓,做一些更聰明,更個性化的東西,它能理解你,幫助你更快更好地醒來。

我們將在本文中構建的個性化鬧鐘系統將從過去的事件中學習並理解它們,以便在下一個鬧鐘中獲得更好的性能。每次使用它都會變得更好。

它會記錄用戶關閉鬧鐘所花的時間(用戶醒來所用的時間),並推薦有助於你更快醒來的鬧鈴調音。

所以,讓我們開始製造鬧鐘系統。我們將在下面一步一步地建造它。

導入所需的包

第一步是將所需的包導入到Python代碼中,以便在構建鬧鐘時使用它們。

如果沒有安裝它們,你需要首先使用pip安裝方法安裝它們。完成安裝步驟後,繼續將它們導入代碼中。

import datetime
import os
import time
import random
import csv
from pygame import mixer
import pandas as pd
import numpy as np

設置Tunes文件夾

下一步是設置一個AlarmTunes文件夾,用戶將在其中存儲他選的鬧鈴。

你可以設置鬧鈴的路徑,我更喜歡Python腳本所在的文件夾創建一個新文件夾。

我們只需要創建一次文件夾,所以我們需要檢查該文件夾是否存在。如果文件夾不存在,我們將創建一個。

# 獲取腳本的當前路徑
path = os.getcwd()

# 設置鬧鈴路徑
alarm_path = path + '\Alarm_Tunes'

# 如果沒有,創建一個。
if not os.path.isdir(alarm_path):
    os.makedirs(alarm_path)

現在,在我們的文件夾被創建後,如果並且僅當文件夾當前是空的,我們將要求用戶添加一些鬧鈴到文件夾,

# 要求用戶在文件夾中添加一些鬧鈴。
while len(os.listdir(alarm_path))==0:
    print("No Alarm Tunes Present. Please add some tunes to the folder before proceeding.")
    confirm = input("Have you added songs? Press Y or N:\t")
    if(confirm=="Y"):
        print("Good! Let's continue!")
        continue
    else:
        continue

因此,如上所述,我們要求用戶至少添加一個鬧鈴。如果沒有鬧鈴,發出警告並再次詢問用戶。

創建CSV文件並定義helper函數

現在,讓我們在跳轉到CSV文件創建部分之前定義一個helper函數。

這個helper函數幫助我們計算兩個Python列表之間的差異。這將在以後的程序中使用。

def List_diff(list1, list2): 
    if len(list1)>=len(list2):
        return (list(set(list1) - set(list2)))
    else:
        return (list(set(list2) - set(list1)))

現在,我們已經編寫了helper函數來計算兩個列表之間的差異。

如果csv文件還不存在的話,我們繼續創建一個CSV文件,csv文件代表鬧鐘的參數。

# 如果沒有csv文件,則創建參數為零的列表
if not os.path.isfile("tune_parameters.csv"):
    tune_list = os.listdir(alarm_path)
    tune_time = [60]*len(tune_list)
    tune_counter = [1]*len(tune_list)
    tune_avg = [60]*len(tune_list)
    tune_prob_rev = [1/len(tune_list)]*len(tune_list)
    tune_prob = [1/len(tune_list)]*len(tune_list)

所以,上面的代碼檢查我們是否有一個CSV文件存在,如果沒有,我們將創建,正如你在上面看到的那樣。我們將在程序結束時將這些保存在CSV文件中。

現在,讓我們解釋一下代碼中每個列表的重要性。讓我們一個接一個地看。

  1. tune_list:它存儲鬧鈴的名稱,它存儲的是鬧鐘路徑中存在的文件列表,從代碼中可以看出。
  2. tune_time:它存儲用戶關閉特定鬧鐘所用的時間總和,即用戶喚醒所用的時間。
  3. tune_counter:它會記錄到現在為止每個鬧鈴的播放次數。
  4. tune_avg:它計算用戶在每次鬧鈴時喚醒和關閉鬧鐘所用的平均時間。
  5. tune_prob_rev:它根據用戶每次鬧鈴所需的平均時間計算一種反向機率。
  6. tune_prob:這是每次播放鬧鈴的機率。它會根據先前的結果不斷更新,並使用tune_rev_prob計算。

這裡需要注意的一點是,我已經為所有這些列表設置了一些默認值,而不是提供零。因為提供零這將對模型產生負面影響,因為從未播放過的列表由於機率為零而永遠不會有機率。

所以,我更傾向於假設這些鬧鈴都運行過一次,平均時間是60秒。這樣我們的工作就容易多了。

現在,如果CSV文件已經存在,我們需要從CSV文件加載數據。

此外,我們需要注意鬧鈴文件夾是否有任何變化。用戶可能添加了新的音樂或刪除了一些現有的音樂。因此,我們要麼需要更新到我們的列表,要麼從文件夾中刪除。

因此,我們使用前面定義的helper函數來找出由文件夾獲得的列表和從CSV文件獲得的列表之間的任何差異。

因此,我們可以對代碼執行所需的操作,並分別使用它們各自的公式更新tune_prob_rev和tune_prob。

# 如果存在csv文件,則從csv文件讀取
else:
    tune_df = pd.read_csv("tune_parameters.csv")
    tune_list_os = os.listdir(alarm_path)
    tune_list = list(tune_df['Tunes'])
    tune_diff = List_diff(tune_list_os, tune_list)
    tune_time = list(tune_df['Delay Times'])
    tune_counter = list(tune_df['Count'])
    tune_avg = list(tune_df['Average'])
    tune_prob_rev = list(tune_df['Reverse Probability'])
    tune_prob = list(tune_df['Probability'])

    if len(tune_list_os)>=len(tune_list):
        for i in range(0,len(tune_diff)):
            tune_list.append(tune_diff[i])
            tune_time.append(60)
            tune_counter.append(1)
            tune_avg.append(60)
            tune_prob_rev.append(0.1)
            tune_prob.append(0.1)

    else:
        for i in range(0,len(tune_diff)):
            tune_diff_index = tune_list.index(tune_diff[i])
            tune_list.pop(tune_diff_index)
            tune_time.pop(tune_diff_index)
            tune_counter.pop(tune_diff_index)
            tune_avg.pop(tune_diff_index)
            tune_prob_rev.pop(tune_diff_index)
            tune_prob.pop(tune_diff_index)

    avg_sum = sum(tune_avg)

    for i in range(0,len(tune_prob_rev)):
        tune_prob_rev[i] = 1 - tune_avg[i]/avg_sum

    avg_prob = sum(tune_prob_rev)

    for i in range(0,len(tune_prob)):
        tune_prob[i] = tune_prob_rev[i]/avg_prob

設置鬧鐘並驗證時間

現在,我們需要定義另一個helper函數來檢查用戶輸入的時間是否正確。因此,我們定義了verify_alarm函數來執行此操作。

# 驗證輸入的時間是否正確。
def verify_alarm(hour,minute,seconds):
    if((hour>=0 and hour<=23) and (minute>=0 and minute<=59) and (seconds>=0 and seconds<=59)):
        return True
    else:
        return False

現在,我們準備好了helper函數。所以,我們需要詢問用戶報警時間。我們將使用一個循環來請求鬧鐘,一旦我們確認時間有效,我們就會中斷。如果無效,我們將再次詢問用戶,直到他輸入有效時間。

# 要求用戶設置報警時間並驗證是否正確。
while(True):
    hour = int(input("Enter the hour in 24 Hour Format (0-23):\t"))
    minute = int(input("Enter the minutes (0-59):\t"))
    seconds = int(input("Enter the seconds (0-59):\t"))
    if verify_alarm(hour,minute,seconds):
        break
    else:
        print("Error: Wrong Time Entered! Please enter again!")

現在,在接受用戶的輸入後,我們將找出當前時間,並將這兩個時間轉換為秒,並找出時間之間的差異。如果差值為負,則意味著鬧鐘將在第二天發出。

然後,我們將使python代碼休眠這幾秒鐘,以便只在需要的時間發出鬧鈴。

# 將報警時間轉換為秒
alarm_sec = hour*3600 + minute*60 + seconds

# 獲取當前時間並將其轉換為秒
curr_time = datetime.datetime.now()
curr_sec = curr_time.hour*3600 + curr_time.minute*60 + curr_time.second

# 計算剩餘報警秒數
time_diff = alarm_sec - curr_sec

# 如果時差為負,則表示鬧鐘為第二天。
if time_diff < 0:
    time_diff += 86400

# 顯示剩餘時間
print("Time left for alarm is %s" % datetime.timedelta(seconds=time_diff))

# 睡到鬧鐘響的時候
time.sleep(time_diff)

播放鬧鈴

現在,我們將播放鬧鈴,我們需要根據機率列表隨機選擇鬧鈴。要播放鬧音,我們將使用pygame.mixer.music庫。我們將無限循環鬧鈴,直到用戶停止。

print("Alarm time! Wake up! Wake up!")
# 根據機率選擇鬧鈴
tune_choice_np = np.random.choice(tune_list, 1, tune_prob)
tune_choice = tune_choice_np[0]
# 獲取索引
tune_index = tune_list.index(tune_choice)

# 播放鬧鈴
mixer.init()
mixer.music.load(alarm_path+"/"+tune_choice)

# 設置loops=-1以確保報警僅在用戶停止時停止!
mixer.music.play(loops=-1)

# 要求用戶停止鬧鐘
input("Press ENTER to stop alarm")
mixer.music.stop()

計算和更新

現在,我們將根據用戶停止報警所需的時間更新列表的值。

我們將找到報警與當前停止報警時間之間的時差。我們將其轉換為秒,然後相應地更新。

# 找到停止鬧鐘的時間
time_stop = datetime.datetime.now()
stop_sec = time_stop.hour*3600 + time_stop.minute*60 + time_stop.second

# 計算時間延遲
time_delay = stop_sec - alarm_sec

# 更新值
tune_time[tune_index] += time_delay
tune_counter[tune_index] += 1
tune_avg[tune_index] = tune_time[tune_index] / tune_counter[tune_index]

new_avg_sum = sum(tune_avg)

for i in range(0,len(tune_list)):
    tune_prob_rev[i] = 1 - tune_avg[i] / new_avg_sum

new_avg_prob = sum(tune_prob_rev)

for i in range(0,len(tune_list)):
    tune_prob[i] = tune_prob_rev[i] / new_avg_prob

合併列表並另存為CSV文件

現在,我們將所有的列表合併到一個多維列表中,然後將其轉換為pandas數據幀,然後將其保存為CSV文件。

# 創建列表
tune_rec = [[[[[[]]]]]]
for i in range (0,len(tune_list)):
    temp=[]
    temp.append(tune_list[i])
    temp.append(tune_time[i])
    temp.append(tune_counter[i])
    temp.append(tune_avg[i])
    temp.append(tune_prob_rev[i])
    temp.append(tune_prob[i])
    tune_rec.append(temp)
tune_rec.pop(0)

# 將合併列錶轉換為數據幀
df = pd.DataFrame(tune_rec, columns=['Tunes','Delay Times','Count','Average','Reverse Probability','Probability'],dtype=float)

# 將數據幀保存為csv
df.to_csv('tune_parameters.csv',index=False)

我們終於完成了智能鬧鐘的製造。要獲得完整的代碼,可以訪問Github存儲庫

連結:https://github.com/shubham1710/Personalised-Alarm-using-Python

關鍵字: