2023年MCMコンペC問題 Wordle予想問題の解答!
質問 1
- 報告された結果の数(報告された結果の数)は毎日変化します。
- この変動を考慮したモデルを開発し、
- モデルを使用して予測間隔。
- 単語の何らかのプロパティは、ハードモードでプレイされたスコアの報告される割合に影響しますか? もしそうなら、どのようにして?そうでない場合は、なぜそうではないのでしょうか?
読み取りデータ
import pandas as pd
import numpy as np
from sklearn.metrics import mean_squared_error
from sklearn.preprocessing import LabelEncoder
import lightgbm as lgb
from datetime import date, timedelta
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
import seaborn as sns
%matplotlib inline
data= pd.read_excel("./Problem_C_Data_Wordle.xlsx",header=1)
data
データの前処理
data = data.drop(columns='Unnamed: 0')
data['Date'] = pd.to_datetime(data['Date'])
data
data.set_index("Date", inplace=True)
data.sort_index(ascending=True,inplace=True)
data=data.reset_index()
data
データ分析
データの傾向
plt.figure(figsize=(15,6))
data["Date"] = pd.to_datetime(data["Date"])
plt.plot(data['Date'],data['Number of reported results'],'r-o', markersize=3)
plt.legend(['Number of reported results'],fontsize=20)
plt.xlabel('Date',fontsize=14)
plt.ylabel('Number of reported results',fontsize=14)
データ配信
plt.figure(figsize=(10,8))
kdeplo=data['Number of reported results']
g=sns.kdeplot(kdeplo,legend=True,shade=True,color='b',label='Number of reported results')
plt.legend(loc='best', fontsize='large')
from scipy.stats import norm, skew
plt.figure(figsize=(10,8))
(mu, sigma) = norm.fit(data['Number of reported results'])
print('\n mu = {:.2f} and sigma = {:.2f}\n'.format(mu, sigma))
g = sns.distplot(data['Number of reported results'], fit=norm)
plt.legend(['Normal dist. ($\mu=$ {:.2f} and $\sigma=$ {:.2f} )'.format(mu, sigma)],
loc='best')
g.set(ylabel='Frequency')
g.set(title=' distribution')
plt.show()
データ統計 - 平均、分散、最大値、最小値...
data.describe()
データの依存関係
corr = abs(data.corr())
corr['Number of reported results'].sort_values(ascending=False)
ハードモードの回数0.922252
コンテスト番号0.821787
1 トライ0.342183
4トライ0.211693
2 トライ0.118527
6 トライ 0.084180
5 トライ 0.077308
3 トライ 0.043624
7 トライ以上 (X) 0.033079
相関係数の絶対値が大きいほど相関が強く、相関係数が1または-1に近いほど相関が強く、相関係数が0に近いほど相関が弱くなります。
- 相関係数:
- 0.8-1.0 非常に強い相関
- 0.6 ~ 0.8 の強い相関
- 0.4-0.6 中程度の相関
- 0.2~0.4の弱い相関
- 0.0-0.2 相関が非常に弱い、または相関がない
ピアソン相関は、積差相関 (または積モーメント相関) としても知られ、20 世紀に英国の統計学者ピアソンによって提案された線形相関を計算する方法です。相関係数の強さは、係数の大きさだけを見るだけでは十分ではありません。
一般的に、絶対値をとった後、0 ~ 0.09 は無相関、0.3 ~ 弱い相関、0.1 ~ 0.3 は弱い相関、0.3 ~ 0.5 は中程度の相関、0.5 ~ 1.0 は強い相関となります。ただし、多くの場合、2 セットのデータに有意な相関があるかどうかをテストするために、有意差検定 (t 検定) も実行する必要があります。これは SPSS で自動的に計算されます。
plt.figure(figsize=(15,15))
g=sns.heatmap(data.corr(),cmap='RdYlGn',annot=True)
plt.show()
回帰予測モデル - XGBoost
XGBoost の最初のプロトタイプは、Chen Tianqi が博士課程在学中に研究プロジェクトを担当していた 2014 年に登場しました。オープンソースの後、C++、Java、Python、R、Julia 言語をサポートする成熟したフレームワークに徐々に発展しました。XGBoost は Extreme Gradient Boosting の頭字語で、Gradient Boosting は実際には勾配ブースティング アルゴリズムです。
Gradient Boosting の名前は、実際には、Gradient Descent + Boosting の 2 つの部分で構成されています。まず第一に、ブースティングとは何かを理解する必要があります。Boostingの意味は、文字通り「ブーストする」という意味で、弱い学習器を改善することで、強い学習器を獲得する過程がブースティングの過程です。弱学習器は、複雑さが低く、トレーニングが容易で、過学習になりにくい非常にシンプルなモデルです。
これらのモデルは、深さが 1 レベルのみのデシジョン ツリーなどのランダムな推測よりも優れていることがよくあります。そして、選択された弱学習器を基本学習器と呼び、これをもとに組み合わせて改良学習器を得る。
評価指標
評価指標が必要であり、回帰問題ではMSE平均二乗誤差が評価対象として選択されることが多いです。式は次のとおりです。
次の式に基づいて MSE の値を計算します。
# 计算 MSE 值
np.square(np.subtract(y, y_)).mean()
XGBoost フレームワークは使用します
まず以下のコマンドを実行してインストールします。
pip install xgboost # 安装
回帰は XGBRegressor() インターフェイスを呼び出します。
XGBoost でモデリングされています。XGBoost の分類メソッドは XGBRegressor です。多くのパラメーターがあります。一般的に使用されるパラメーターを見てみましょう。
- max_ Depth – 基本学習器のツリーの最大の深さ。
- learning_rate – 学習率を向上させます。
- n_estimators – デシジョン ツリーの数。
- gamma – ノード分割に必要な最小損失関数ドロップを指定するペナルティ係数。
- booster - ブースティング アルゴリズム (gbtree、gblinear、または dart) を指定します。
- n_jobs – マルチスレッドの数を指定します。
- reg_alpha – L1 正則化の重み。
- reg_lambda – L2 正則化の重み。
- scale_pos_weight – 正と負の重量バランス。
- random_state – 乱数シード。
デフォルトのパラメーターを使用してモデルを初期化します。
- XGBRegressor() を呼び出してモデルをトレーニングし、評価します。
import xgboost as xgb
model_r = xgb.XGBRegressor()
データセットを 80% のトレーニング データと 20% のテスト データに分割します
X = data.drop(labels='Number of reported results', axis=1)
y = data['Number of reported results'] # 目标值
from sklearn.model_selection import train_test_split
# 划分数据集,80% 训练数据和 20% 测试数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
X_train.shape, X_test.shape, y_train.shape, y_test.shape
訓練データを使用した訓練
- 訓練データを使用した訓練
- テストデータを使用して R^2 評価指標を計算します
model_r.fit(X_train, y_train) # 使用训练数据训练
model_r.score(X_test, y_test) # 使用测试数据计算 R^2 评估指标
パラメータ
XGBClassifier と XGBRegressor の両方にパラメータ目標があります。
- 分類問題を解く場合は、デフォルトで object='binary:logistic' が選択され、回帰問題の場合はデフォルトで object='reg:linear' が選択されます。
- 文字通りの意味から、これは学習者が完了するタスクの種類を指定するパラメーター (通常はターゲット パラメーターと呼ばれます) であることがわかるはずです。
そして、回帰問題を解くとき、このパラメータは通常 reg:linear (reg:squarederror に変更予定) と reg:logistic となり、それぞれ線形回帰とロジスティック回帰を表します。
決定木を描く
XGBoost は、モデルのトレーニング後に決定サブツリーを描画できる xgb.plot_tree メソッドを提供します。
- 使用する場合は、モデルとサブツリーのシリアル番号を渡すだけで、必要な方を描画できます。
Graphviz パッケージをインストールする
# 安装 graphviz 包
!pip install graphviz
from matplotlib import pyplot as plt
from matplotlib.pylab import rcParams
%matplotlib inline
# 设置图像大小
rcParams['figure.figsize'] = [50, 10]
xgb.plot_tree(model_t, num_trees=1)
相互検証
相互検証に XGBoost を使用する方法。
相互検証は、機械学習でモデルを迅速に評価するための重要な方法です。
- データセットを N 個のサブセットに分割し、そのうちの N-1 個を使用してモデルをトレーニングし、最後に残りの 1 個のサブセットで評価できます。
順番にポーリングし、最終的に N 回の評価の平均指標を求め、モデルの最終評価結果となります。
- XGBoost は、相互検証プロセスを完了するための xgb.cv メソッドを提供します。
したがって、相互検証ではトレーニング セットとテスト セットを別々に分割する必要がなく、完全なデータ セットを直接使用できます。
# 依次传入特征和目标值
data_d = xgb.DMatrix(data=X, label=y)
xgb.cv(dtrain=data_d , params={
'objective': 'reg:squarederror'}, nfold=5, as_pandas=True)
上記パラメータのうち、
- dtrain はデータセットを渡します。params はモデルのカスタムパラメータです。
- nfold は交差検証によって分割された N 個のサブセットです。
- as_pandas は、最終出力が DataFrame スタイルになることを示します。
デフォルトでは、XGBoost はブースト反復を 10 回実行するため、10 行の出力が表示されます。
- もちろん、num_boost_round パラメーターを変更して、最大反復回数をカスタマイズできます。
質問2
- 将来の日付に対する特定の将来の解の単語については、
- 報告される結果の分布を予測できるモデルを開発します。
- 言い換えると、将来の日付 (1、2、3、4、5、6、X) の相対パーセンテージを予測します。。
- モデルと予測にはどのような不確実性が関連付けられていますか?
- 2023 年 3 月 1 日に「EERIE」という単語が予測されるという具体的な例を挙げてください。
- モデルの予測にどの程度自信がありますか?
母音はa、e、i、o、uの 5 つで、残りは子音です。
子音は、b、c、d、f、g、h、j、k、l、m、n、p、q、r、s、t、v、w、x、y、z です。
Vowel = ['a','e','i','o','u']
Consonant = list(set(small).difference(set(Vowel)))
def count_Vowel(s):
c = 0
for i in range(len(s)):
if s[i] in Vowel:
c+=1
return c
def count_Consonant(s):
c = 0
for i in range(len(s)):
if s[i] in Consonant:
c+=1
return c
df['Vowel_fre'] = df['Word'].apply(lambda x:count_Vowel(x))
df['Consonant_fre'] = df['Word'].apply(lambda x:count_Consonant(x))
時間的特徴変換
df["year"] = df.index.year
df["quarter"] = df.index.quarter
df["month"] = df.index.month
df["week"] = df.index.week
df["weekday"] = df.index.weekday
データの標準化
データの標準化とは、元のデータを特定の数学的変換方法を通じて特定の比率に従って変換し、0 ~ 1 または -1 ~ 1 の間隔などの小さな特定の間隔に収まるようにすることです。
- 異なる変数間の性質、次元、桁数などの特性属性の違いを取り除き、無次元の相対値に変換し、
- それは、各指標の値が定量的に同じレベルになるように値を標準化することです。
- これにより、さまざまな単位または桁数の指標の包括的な分析と比較が容易になります。
from sklearn.preprocessing import StandardScaler
# 标准化
std = StandardScaler()
X1 = std .fit_transform(X)
アンサンブル学習 - ランダムフォレスト
アンサンブル学習は、複数の個別の学習者 (ベース学習者と呼ばれます) を構築および組み合わせて、学習タスクを完了することです。例として。以下の表において、○は分類が正しいことを意味し、×は分類が間違っていることを意味します。
ランダムフォレスト
ランダム フォレストは、決定木ベースの学習器です。ただし、属性の選択はデシジョン ツリーと同じではありません。
- ランダムフォレストでは、基本決定木学習器が各ノードのノードの属性セットから K 個の属性を含むサブセットをランダムに選択し、そのサブセットから最適な属性を選択して分割します。
- これは「良いが異なる」条件を満たします。ランダム フォレストは計算オーバーヘッドが低く、機械学習アルゴリズムの中でも比較的高度なアルゴリズムです。
sklearnパラメータの調整
相互検証方法のチューニング
まず、n_estimators、max_ Depth を調整します。
- まず、特徴の数を観察します。これにより、max_ Depth などのパラメーターの範囲が決まります。
- 次に、相互検証方法を使用してパラメーターを調整します。
最適なパラメータ n_estimators=100、max_ Depth=10 を取得します。
def para_tune(para, X, y): #
clf = RandomForestClassifier(n_estimators=para) # n_estimators 设置为 para
score = np.mean(cross_val_score(clf, X, y, scoring='accuracy'))
return score
def accurate_curve(para_range, X, y, title):
score = []
for para in para_range:
score.append(para_tune(para, X, y))
plt.figure()
plt.title(title)
plt.xlabel('Paramters')
plt.ylabel('Score')
plt.grid()
plt.plot(para_range, score, 'o-')
return plt
g = accurate_curve([2, 10, 50, 100, 150], X, y, 'n_estimator tuning')
def para_tune(para, X, y):
clf = RandomForestClassifier(n_estimators=300, max_depth=para)
score = np.mean(cross_val_score(clf, X, y, scoring='accuracy'))
return score
def accurate_curve(para_range, X, y, title):
score = []
for para in para_range:
score.append(para_tune(para, X, y))
plt.figure()
plt.title(title)
plt.xlabel('Paramters')
plt.ylabel('Score')
plt.grid()
plt.plot(para_range, score, 'o-')
return plt
g = accurate_curve([2, 10, 20, 30, 40], X, y, 'max_depth tuning')
scikit-learn自動パラメータチューニング機能 GridSearchCV
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import learning_curve
def plot_learning_curve(estimator, title, X, y, cv=10,
train_sizes=np.linspace(.1, 1.0, 5)):
plt.figure()
plt.title(title) # 设置图的 title
plt.xlabel('Training examples') # 横坐标
plt.ylabel('Score') # 纵坐标
train_sizes, train_scores, test_scores = learning_curve(estimator, X, y, cv=cv,
train_sizes=train_sizes)
train_scores_mean = np.mean(train_scores, axis=1) # 计算平均值
train_scores_std = np.std(train_scores, axis=1) # 计算标准差
test_scores_mean = np.mean(test_scores, axis=1)
test_scores_std = np.std(test_scores, axis=1)
plt.grid() # 设置背景的网格
plt.fill_between(train_sizes, train_scores_mean - train_scores_std,
train_scores_mean + train_scores_std,
alpha=0.1, color='g') # 设置颜色
plt.fill_between(train_sizes, test_scores_mean - test_scores_std,
test_scores_mean + test_scores_std,
alpha=0.1, color='r')
plt.plot(train_sizes, train_scores_mean, 'o-', color='g',
label='traning score') # 绘制训练精度曲线
plt.plot(train_sizes, test_scores_mean, 'o-', color='r',
label='testing score') # 绘制测试精度曲线
plt.legend(loc='best')
return plt
clf = RandomForestClassifier()
para_grid = {
'max_depth': [10], 'n_estimators': [100], 'max_features': [1, 5, 10], 'criterion': ['gini', 'entropy'],
'min_samples_split': [2, 5, 10], 'min_samples_leaf': [1, 5, 10]}#对以上参数进行网格搜索
gs = GridSearchCV(clf, param_grid=para_grid, cv=3, scoring='accuracy')
gs.fit(X, y)
gs_best = gs.best_estimator_ #选择出最优的学习器
gs.best_score_ #最优学习器的精度
g = plot_learning_curve(gs_best, 'RFC', X, y)#调用实验2中定义的 plot_learning_curve 绘制学习曲线
質問3
- 解決策の単語を難易度別に分類するモデルを開発して要約します。
- 各カテゴリに関連付けられた特定の単語の属性を特定します。
- あなたのモデルを使用して、「EERIE」という単語はどのくらい難しいですか?
- 分類モデルの精度について議論します。
Kmeans クラスタリング アルゴリズム
アルゴリズム思考
連続反復を通じて k 値を見つけて除算法を形成し、k クラスターの平均値を使用して対応する種類のサンプルを表すときに得られる全体の誤差が最小になるようにします。
- 同じクラスター内のオブジェクトの類似性は高くなりますが、異なるクラスター内のオブジェクトの類似性は低くなります。
- K 平均法アルゴリズムの基礎は最小誤差二乗和基準であり、その機能は次のとおりです。
上の式で、μc(i) は i 番目のクラスターの平均値を表します。 - さまざまなクラスターに分割されたサンプルが類似しているほど、それらのクラスターとクラスの平均との間の二乗誤差は小さくなります。
- 次に、すべてのクラスに対して計算された誤差二乗が累積され、再度合計されます。
- つまり、J の値は小さいほど良いと考えられます。
アルゴリズムの実装手順
k 平均法アルゴリズムは、サンプルを k 個のクラスター中心にクラスター化するもので、k 値は私たちが指定します。つまり、データをいくつかのカテゴリーに分割します。
具体的なアルゴリズムは次のように説明されます。
- クラスター化する必要があるデータについては、k 個のクラスター重心点をランダムに選択します。
- 各点からクラスター重心点までの距離を求め、それが属するクラスを計算し、特定の値に収束するまで繰り返します。
# 导入 KMeans 估计器
from sklearn.cluster import KMeans
est = KMeans(n_clusters=4) # 选择聚为 4 类
est.fit(X)
y_kmeans = est.predict(X) # 预测类别,输出为含0、1、2、3数字的数组
# 为预测结果上色并可视化
plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=50, cmap='viridis')
centers = est.cluster_centers_ # 找出中心
plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.5) # 绘制中心点
K 平均法アルゴリズム: 期待値の最大化
K-Means は、期待値最大化法を使用して結果を得るアルゴリズムです。期待値の最大化は 2 つのステップで説明でき、その動作原理は次のとおりです。
1. クラスターの中心をいくつか推測します。
2. 収束するまで繰り返します。
期待ステップ (E ステップ): 点を最も近いクラスターの中心点に割り当てます。
最大化ステップ (M ステップ): クラスターの中心点をすべての点座標の平均として設定します。
from sklearn.metrics import pairwise_distances_argmin # 最小距离函数
import numpy as np
def find_clusters(X, n_clusters, rseed=2):
# 1.随机选择簇中心点
rng = np.random.RandomState(rseed)
i = rng.permutation(X.shape[0])[:n_clusters]
centers = X[i]
while True:
# 2a.基于最近的中心指定标签
labels = pairwise_distances_argmin(X, centers)
# 2b.根据点的平均值找到新的中心
new_centers = np.array([X[labels == i].mean(0)
for i in range(n_clusters)])
# 2c.确认收敛
if np.all(centers == new_centers):
break
centers = new_centers
return centers, labels
centers, labels = find_clusters(X, 4)
plt.scatter(X[:, 0], X[:, 1], c=labels,
s=50, cmap='viridis') # 绘制聚类结果