1、百度百科的解释:冰雹猜想
2、本练习的目的是在假设冰雹猜想正确的情况下,利用数据挖掘的方法找出 n 和 fn 之间的关系,其中 n 是输入的整数 1、2、3..., fn 则是 n 经过一定规则的变换后得到 1 所经过的步骤次数,规则为 如果 n 是奇数则变为 3*n + 1,如果是偶数则为 n/2
3、生成数据
#! usr/bin/env python
# coding:utf8
"""
__author__ = "LCG22"
__date__ = "2016-11-22"
本程序目的是生成用于数据挖掘的冰雹猜想的数据,主要是 n 和 fn,其中 n 是输入的整数 1、2、3...,
fn 则是 n 经过一定规则的变换后得到 1 所经过的步骤次数,规则为 如果 n 是奇数则变为 3*n + 1,如果是偶数则为 n/2
"""
import pandas as pd
DATA_PATH = {
"100": r"data_100.csv",
"1000": r"data_1000.csv",
"10000": r"data_10000.csv",
"100000": r"data_100000.csv",
"1000000": r"data_1000000.csv",
"10000000": r"data_10000000.csv"
}
def fn_num(n, i=0):
"""
输出 fn
:param n:
:param i: 已经经过了多少步
:return:
"""
if n == 2:
return i + 1
else:
if n % 2 == 0:
nn = n / float(2)
i += 1
return fn_num(nn, i)
else:
nn = 3*n + 1
i += 1
return fn_num(nn, i)
def main(save_path, n_max=100):
fn_list = []
for n in range(1, n_max):
fn = fn_num(n)
fn_list.append(fn)
data_df = pd.DataFrame({"n": [n for n in range(1, n_max)], "fn": fn_list})
data_df.to_csv(save_path, index=False)
if __name__ == '__main__':
main(DATA_PATH["100"], 100)
main(DATA_PATH["1000"], 1000)
main(DATA_PATH["10000"], 10000)
main(DATA_PATH["100000"], 100000)
main(DATA_PATH["1000000"], 1000000)
main(DATA_PATH["10000000"], 10000000)
4、利用 sklearn 的相关机器学习的方法来找出 n 和 fn 的关系
在第三步的时候我们生成了很多个数量级的数据,最小的是100,最大的是1千万。而在第四步中,我们会首先进行数据可视化,因为 100 的数据量太小,故选用了 1000 的数据进行可视化
可视化:
代码部分:
data_df = pd.read_csv(read_path)
# 画图观察数据的分布
plt.plot(data_df.n, data_df.fn)
plt.xlabel(u"n")
plt.ylabel(u"fn")
plt.show()
plt.close()
图像部分:
图中的 x 轴的 n 表示的是整数 1- 1000(生成的数据中并没有包括 0 ,这是因为 0 是不是偶数仍有争议,故不使用 0 来生成数据)而 y 轴的 fn 则表示的是从整数 n 经过规则变换后变为 1 所经过的步骤。而由图中可以明显看出:
①、n 和 fn 并不是线性关系
②、n 和 fn 也并不是指数关系。图中可以看出 fn 并没有随着 n 的大幅增加而大幅增加,所以显然不是指数关系
③、fn 并不是总是随着 n 的增加而增加,故 n 和 fn 的关系也不是单调递增或递减
拟合:
下面是整篇文章的重头戏,将会使用到 sklearn 库中的机器学习方法,对 fn 进行拟合
① 贝叶斯岭回归 (Beyesian Ridge Regression)
代码部分:
# 使用贝叶斯岭回归(Bayesian Ridge Regression)方法进行拟合
X = list(data_df.n.apply(lambda x: [x]))
# X = [[i] for i in X]
y = data_df.fn
clf = BayesianRidge(compute_score=True)
clf.fit(X, y)
pre = clf.predict(X)
# 数据可视化
lw = 2
plt.plot(pre, color="lightgreen", label="Bayesian Ridge Regression")
plt.plot(y, color="gold", label="y")
plt.show()
plt.close()
图像部分:
通过图像明显可以看出贝叶斯岭回归的拟合效果并不好,因为贝叶斯岭回归拟合的是线性关系,但是显然我们的数据集并不是线性的
②多项式
代码部分:
# 多项式拟合
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
degree = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40]
for d in degree:
clf = Pipeline([("poly", PolynomialFeatures(degree=d)),
("linear", LinearRegression(fit_intercept=False))])
clf.fit(X, y)
y_test = clf.predict(X)
plt.plot(X, y_test, linewidth=2)
plt.plot(X, y)
plt.grid()
plt.legend([str(i) for i in degree], loc="upper left")
plt.show()
plt.close()
图像部分:
通过图像也可以看出多项式的拟合效果不好
其它方法则等学习了更多的拟合相关的方法再更新