用Python構建個性化智能鬧鐘

做者|Kumar Shubham
編譯|VK
來源|Towards Data Sciencepython

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

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

因此,讓咱們更上一層樓,作一些更聰明,更個性化的東西,它能理解你,幫助你更快更好地醒來。app

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

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

因此,讓咱們開始製造鬧鐘系統。咱們將在下面一步一步地建造它。函數

導入所需的包

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

若是沒有安裝它們,你須要首先使用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/shubham171...

原文連接:https://towardsdatascience.co...

歡迎關注磐創AI博客站:
http://panchuang.net/

sklearn機器學習中文官方文檔:
http://sklearn123.com/

歡迎關注磐創博客資源彙總站:
http://docs.panchuang.net/

相關文章
相關標籤/搜索