本文包括邮箱登入,邮件数据分析,长短时神经网络分析,时间序列分析。
参考文献原文为对google邮箱的翻译
本文利用imapclient
库进行登入,网易邮箱登入会遇到错误可以refer一下链接 本文主要获取邮件收取的时间序列,需要获取邮件更多信息可以参考 。获取2016年1月1日开始至今的邮件。
import imapclient
import pandas as pd
import getpass
youremail = input()
yourpassword = getpass.getpass()
imapObj = imapclient.IMAPClient("imap.163.com", ssl=True) #若使用其他邮箱 可以换为其他邮箱的IMAP服务器地址
imapObj.login(youremail, yourpassword)
imapObj.select_folder("INBOX", readonly=True)
UIDs = imapObj.search('(SINCE "01-Jan-2016")')
mails = []
for msgid, data in imapObj.fetch(UIDs, ["ENVELOPE"]).items():
envelope = data[b"ENVELOPE"]
date = envelope.date
if envelope.subject is not None:
subject = envelope.subject.decode()
else:
subject = None
mails.append((subject, date))
mail_df = pd.DataFrame(mails)
mail_df.columns = ["Subject", "Date"]
mail_df["Date"] = pd.to_datetime(mail_df["Date"])
mail_df = mail_df.set_index("Date")
print("A total of {} e-mails loaded.".format(len(mail_df)))
python2 环境可以运行,换完python3 环境会遇到以下问题[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:748)
暂未解决
本节对数据按照小时和星期进行总汇分析,并进行可视化。
对于可视化的色彩渐变可参考,更改调色板可参考。
#分析汇总代码
import calendar
import seaborn as sns
import matplotlib.pyplot as plt
weekdays = [calendar.day_name[i] for i in range(7)]
# E-Mails per Hour
per_hour = pd.DataFrame(mail_df["Subject"].resample("h").count())
per_hour_day = (
per_hour.groupby([per_hour.index.hour]).sum()
/ per_hour.groupby([per_hour.index.hour]).count()
)
per_hour_day.reset_index(inplace=True)
per_hour_day.columns = ["Hour", "Count"]
# E-Mails per day
per_day = pd.DataFrame(mail_df["Subject"].resample("d").count())
per_day_week = (
per_day.groupby([per_day.index.weekday]).sum()
/ per_day.groupby([per_day.index.weekday]).count()
)
per_day_week.reset_index(inplace=True)
per_day_week.columns = ["Weekday", "Count"]
per_day_week["Weekday"] = weekdays
#可视化代码
def return_cmap(data):
# Function to create a colormap
v = data["Count"].values
colors = plt.cm.YlGnBu((v - v.min()) / (v.max() - v.min()))
return colors
plt.figure(figsize=(12, 10), dpi=600)
plt.subplot(2, 1, 1)
cmap = return_cmap(per_hour_day)
sns.barplot(x="Hour", y="Count", data=per_hour_day, palette=cmap)
plt.title("Emails per hour")
plt.subplot(2, 1, 2)
cmap = return_cmap(per_day_week)
sns.barplot(x="Weekday", y="Count", data=per_day_week, palette=cmap)
plt.title("Emails per weekday")
plt.show()
print("Average number of emails per day: {:.2f}".format(per_hour_day.sum()["Count"]))
(本文图为做作邮箱的个人邮件信息)在一天中,邮件分发主要时间段为8点到18点,也是主要的工作时间,其中10-11点获取的邮件最多。在一周中,Mon-Thur的邮件较多,Fir开始邮件量减少,周末邮件也相对较少。由于每小时电子邮件量均有各自特征,因此对每小时进行预测是没有意义的,作者将尝试预测每天的电子邮件工作量
在大多数情况下,发送方互相不认识,因此可以假设它们在统计上是独立的。另外,我们可以将收件近似为泊松过程(Poissonian),它的标准偏差等于平均值。由于分布是随机的,12封电子邮件的期望的RMSE值至少为3.5(sqrt(11.95)~3.461)。
RMSE与标准差对比:标准差是用来衡量一组数自身的离散程度,而均方根误差是用来衡量观测值同真值之间的偏差,它们的研究对象和研究目的不同,但是计算过程类似。
如果想进一步阅读,可以看三种排队模型,本文用埃尔朗模型。这里提供一篇用该分布做的机场排队模型的分布。
为了创建基线模型,我们可以使用历史数据中的查询表。对于任意的某一天,计算在一天之前收到的电子邮件数量。为了对模型进行基准测试,我使用一个移动窗口来创建查询表,并计算到第二天的预测差异值。
from sklearn.metrics import mean_squared_error
import numpy as np
data = per_day.copy()
test_split = int(len(data) * 0.8)
pred_base = []
for i in range(len(data) - test_split):
train_data = data[i : test_split + i]
test_data = data.iloc[test_split + i]
train_data_week = (
train_data.groupby([train_data.index.weekday]).sum()
/ train_data.groupby([train_data.index.weekday]).count()
)
baseline_prediction = train_data_week.loc[test_data.name.weekday()]
pred_base.append(baseline_prediction.values)
test_data = data[test_split:]
mse_baseline = mean_squared_error(test_data.values, pred_base)
print("RMSE for BASELINE {:.2f}".format(np.sqrt(mse_baseline)))
基线模型得到的RMSE为7.86 ,相对于3.5的预期值,这个结果还不错。
作为进阶模型,我们将使用长短时记忆(LSTM)神经网络。在这里可以找到对LSTM的很好的介绍(https:/machinelearningmaster ery.com/time-Series-prediction-lstm-rrurn-neuro-network-python-keras/)。
在这里,我们将窗口设置为6天,并让模型预测第7天。
利用python3进行预测。
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
def get_window_data(data, window):
# Get window data and scale
scaler = MinMaxScaler(feature_range=(0, 1))
data = scaler.fit_transform(data.reshape(-1, 1))
X,y = [],[]
for i in range(len(data) - window - 1):
X.append(data[i : i + window])
y.append(data[i + window + 1])
X = np.asarray(X)
y = np.asarray(y)
return X, y, scaler
window_size = 6
X, y, scaler = get_window_data(per_day["Subject"].values, window_size)
X_train = X[:test_split]
X_test = X[test_split:]
y_train = y[:test_split]
y_test = y[test_split:]
model = Sequential()
model.add(LSTM(50, input_shape=(window_size, 1)))
model.add(Dropout(0.2))
model.add(Dense(1))
model.add(Activation("linear"))
model.compile(loss="mse", optimizer="adam")
history = model.fit(X_train,y_train,epochs=20,batch_size=1,validation_data=(X_test, y_test),verbose=2,shuffle=False,)
# plot history
plt.figure(figsize=(6, 5), dpi=600)
plt.plot(history.history["loss"], 'darkred', label="Train")
plt.plot(history.history["val_loss"], 'darkblue', label="Test")
plt.title("Loss over epoch")
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.show()
mse_lstm = mean_squared_error(
scaler.inverse_transform(y_test),
scaler.inverse_transform(model.predict(X_test)),
)
print("RMSE for LSTM {:.2f}".format(np.sqrt(mse_lstm)))
接下来,我们将使用facebook的Prophet库(https://github.com/facebook/prophet)。它是一个加性模型,我们可以用年、周和日的季节性来拟合非线性趋势。同样地,我们将把数据分成训练集和测试集,并计算RMSE值。
在python2 上运行。
from fbprophet import Prophet
from tqdm import tqdm
prophet_data = data.reset_index()
prophet_data["ds"] = prophet_data["Date"]
prophet_data["y"] = prophet_data["Subject"]
pred = []
for i in tqdm(range(len(data) - test_split)):
data_to_fit = prophet_data[: (test_split + i)]
prophet_model = Prophet(interval_width=0.95)
prophet_model.fit(data_to_fit)
prophet_forecast = prophet_model.make_future_dataframe(periods=1, freq="d")
prophet_forecast = prophet_model.predict(prophet_forecast)
pred.append(prophet_forecast["yhat"].iloc[-1])
mse_prophet = mean_squared_error(test_data.values, pred)
print("RMSE for PROPHET {:.2f}".format(np.sqrt(mse_prophet)))
从RMSE来看,Prophet模型实现了最佳性能。现在让我们研究一下这是为什么。为此,我们绘制模型的各个构成部分,以便更好地理解模型所做的工作。这只需要使用性能指标函数就可以输出结果。
通过检查Prophet模型的构成,我们可以看到它识别出了数据中的关键趋势。总趋势表明邮件数量在整体上不断增加。每周的季节性准确地描绘了工作日/周末的时间波动。每年的季节性显示主要节日,即新年电子邮件很少,但在圣诞节前有所增加,而低点在9月份。
总结:预测邮件数量。
最后,我们使用Prophet模型作为我们的预测工具。为此,我们再次登录到IMAP服务器,并使用自2016年1月1日以来的所有历史数据来训练我们的预测模型。训练完毕后,我们绘制了前一周的历史数据和下一周的预测情况。
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
from fbprophet import Prophet
import imapclient
import pandas as pd
import getpass
'''
youremail ='suke_will@163.com'
yourpassword = getpass.getpass()
imapObj = imapclient.IMAPClient("imap.gmail.com", ssl=True)
imapObj.login(youremail, yourpassword)
imapObj.select_folder("INBOX", readonly=True)
UIDs = imapObj.search('(SINCE "01-Jan-2016")')
mails = []
for msgid, data in imapObj.fetch(UIDs, ["ENVELOPE"]).items():
envelope = data[b"ENVELOPE"]
date = envelope.date
if envelope.subject is not None:
subject = envelope.subject.decode()
else:
subject = None
mails.append((subject, date))
mail_df = pd.DataFrame(mails)
mail_df.columns = ["Subject", "Date"]
mail_df["Date"] = pd.to_datetime(mail_df["Date"])
mail_df = mail_df.set_index("Date")
data = pd.DataFrame(mail_df["Subject"].resample("d").count())
'''
data = per_day
prophet_model = Prophet(interval_width=0.95)
prophet_data = data.reset_index()
prophet_data["ds"] = prophet_data["Date"]
prophet_data["y"] = prophet_data["Subject"]
prophet_model.fit(prophet_data)
prophet_forecast = prophet_model.make_future_dataframe(periods=7, freq="d")
prophet_forecast = prophet_model.predict(prophet_forecast)
fig1 = prophet_model.plot(prophet_forecast)
datenow = datetime.now()
dateend = datenow + timedelta(days=7)
datestart = dateend - timedelta(days=14)
plt.xlim([datestart, dateend])
plt.title("Email forecast", fontsize=20)
plt.xlabel("Day", fontsize=20)
plt.ylabel("Emails expected", fontsize=20)
plt.axvline(datenow, color="k", linestyle=":")
plt.show()
讨论
LSTMS和Facebook的Prophet模型提供了一种简单易懂的方法来预测电子邮件数量,而且具有相当好的准确性。考虑到模型的基本机制,这一结果是可以理解的。LSTM预测是基于一组最后的值,因此不太容易考虑到季节差异。相比之下,Prophet模型发现并显示了季节性。
该模型可以对规划未来的工作量或人员配置提供参考。
这类问题的一个关键挑战是,如果只有零星的偶发事件,那么内在趋势是不可预测的。
最后别忘了,我们的基线模型的表现就很不错,所以你不一定总是需要复杂的机器学习算法来搭建你的预测模型。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章