作者|Kumar Shubham
编译|VK
来源|Towards Data Science
你可能之前有见过有人使用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文件中。
现在,让我们解释一下代码中每个列表的重要性。让我们一个接一个地看。
- tune_list:它存储闹铃的名称,它存储的是闹钟路径中存在的文件列表,从代码中可以看出。
- tune_time:它存储用户关闭特定闹钟所用的时间总和,即用户唤醒所用的时间。
- tune_counter:它会记录到现在为止每个闹铃的播放次数。
- tune_avg:它计算用户在每次闹铃时唤醒和关闭闹钟所用的平均时间。
- tune_prob_rev:它根据用户每次闹铃所需的平均时间计算一种反向概率。
- 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/