《基于LSTM神经网络的双色球蓝球数字预测》

结论:没有任何作用,基本可以断定这是真正随机的数字。
《基于LSTM神经网络的双色球蓝球数字预测》_第1张图片
LSTM神经网络,单步预测,循环2000次,100个神经元,无dropout。
蓝线:最近50期蓝球数字
橙线:LSTM网络预测数字
绿线:蓝线 - 橙线,相差值
结果就是,没有预测出任何有用的数据

过程:
步骤一:利用爬虫获取500彩票网的历年双色球蓝球数字
步骤二:整理并保存好数据。
步骤三:利用LSTM神经网络进行单步预测

程序来源:
程序一,爬虫程序:自己写的小爬虫。
500彩票网的编码格式是gbk,但有点问题,网站程序员貌似混进了点非法字符,遇到了就选择忽略就行。
500彩票网的数据最早可以追溯到2003年2月23日的第03001期,往后每年的开奖次数有所不同。
2003年共开了03001~03089,共89期
2004年共开了04001~04122,共122期
2005年共开了05001~05153,共153期
2006年共开了06001~06154,共154期
2007年共开了07001~07153,共153期
2008年共开了08001~08154,共154期
2009年共开了09001~09154,共154期
2010年共开了10001~10153,共153期
2011年共开了11001~11153,共153期
2012年共开了12001~12154,共154期
2013年共开了13001~13154,共154期
2014年共开了14001~14152,共152期
2015年共开了15001~15154,共154期
2016年共开了16001~16153,共153期
2017年共开了17001~17154,共154期,其中第17001期数据崩了,没有数据。
2018年共开了18001~18153,共153期
2019年共开了19001~19151,共151期
2020年共开了20001~20134,共134期
2021年共开了21001~21023,至今只有23期

彩票网的网址也很好解析,就是https://kaijiang.500.com/shtml/ssq/(期数).shtml
找个列表循环起来就行。

import urllib.request
import pandas as pd

blue_data = []
blue_data_a = []


def url_pachong():
    global response, blue_data
    blue_list = [88,121,152,153,152,153,153,152,152,153,153,151,153,152,153,152,150,133,22]
    for i in range(18):
        for j in range(blue_list[i]):
            if i < 7:
                response = urllib.request.urlopen("https://kaijiang.500.com/shtml/ssq/0" + str((i+3)*1000+1+j) + ".shtml")
                print(str((i+3)*1000+1+j))
            else:
                response = urllib.request.urlopen("https://kaijiang.500.com/shtml/ssq/" + str((i+3)*1000+1+j) + ".shtml")
                print(str((i+3)*1000+1+j))
            if (i + 3) * 1000 + 1 + j == 17001:    #500彩票网中,第17001次开奖结果炸了,没有数据,自动忽略
                continue
            html = response.read().decode("gbk", "ignore")    #500彩票网的网站程序员混进了一些gbk的非法字符,选择自动忽略非法字符
            html_data = html.find('
  • ') #找到蓝球数字所在的地方 print(html.find('
  • ')) print(html[html_data + 22] + html[html_data + 23]) blue_data.append(int(html[html_data + 22] + html[html_data + 23])) blue_data_a.append(int(html[html_data + 22] + html[html_data + 23])) test = pd.DataFrame(columns=['data'], data=blue_data) test.to_csv('C:/Users/小幻月/Desktop/双色球数据爬取/bull_data_'+str(i)+'.csv') print("阶段%d完成" % int(i+1)) blue_data = [] if __name__ == "__main__": url_pachong() test = pd.DataFrame(columns=['data'], data=blue_data) test.to_csv('C:/Users/小幻月/Desktop/双色球数据爬取/blue_data_a.csv')
  • 程序二,数据整理程序:自己写的
    为啥要这个程序呢,可能是因为我自己的网络不够稳定,所以有时候爬虫网页加载不出来,导致这一步html_data = html.find('

  • ')没法找到对应的字符,返回错误-1,导致后面的int(html[html_data + 22]语句类型错误,然后程序就退出来了(其实我觉得可以加个try语句进行重试的),不过我选择每完成一个阶段就保存成一个文件,然后再整合到一个文件中。

    程序比较弱智:

    from pandas import read_csv
    import pandas as pd
    
    data = []
    data_blue = []
    
    
    def file_open():
        global data_blue, data
        for i in range(19):
            data = read_csv('blue_data_%d.csv' % i, index_col=0, squeeze=True).values
            data_blue.append(list(data))
            #现在的数据是个二维列表,对其进行降维,转变为字符串,再删去'['和']'
            b = str(data_blue)
            b = b.replace('[', '')
            b = b.replace(']', '')
            data_blue = list(eval(b))
            data = []
            print(i)
        test = pd.DataFrame(columns=['data'], data=data_blue)
        test.to_csv('C:/Users/小幻月/Desktop/双色球数据爬取/data_blue.csv')
    
    
    if __name__ == '__main__':
        file_open()
    

    程序三,LSTM神经网络单步预测:github上下载的例程,进行了一点点地修改。

    from pandas import DataFrame
    from pandas import Series
    from pandas import concat
    from pandas import read_csv
    from pandas import datetime
    from sklearn.metrics import mean_squared_error
    from sklearn.preprocessing import MinMaxScaler
    from keras.models import Sequential
    from keras.layers import Dense
    from keras.layers import Dropout
    from keras.layers import LSTM
    from keras.models import save_model
    from keras.models import load_model
    from math import sqrt
    from matplotlib import pyplot
    import numpy
    
    
    # 构建差分序列
    def difference(dataset, interval=1):
        diff = list()
        for i in range(interval, len(dataset)):
            value = dataset[i] - dataset[i - interval]
            diff.append(value)
        return Series(diff)
    
    
    # 将数据转换为监督型学习数据,NaN值补0
    def timeseries_to_supervised(data, lag=1):
        df = DataFrame(data)
        columns = [df.shift(i) for i in range(1, lag + 1)]
        columns.append(df)
        df = concat(columns, axis=1)
        df.fillna(0, inplace=True)
        return df
    
    
    def scale(train, test):
        # 创建一个缩放器
        scaler = MinMaxScaler(feature_range=(-1, 1))
        scaler = scaler.fit(train)
        print(train)
        # 将train从二维数组的格式转化为一个23*2的张量
        # train = train.reshape(train.shape[0], train.shape[1])
        # 使用缩放器将数据缩放到[-1, 1]之间
        train_scaled = scaler.transform(train)
        print(train_scaled)
        # transform test
        # test = test.reshape(test.shape[0], test.shape[1])
        test_scaled = scaler.transform(test)
        return scaler, train_scaled, test_scaled
    
    
    def fit_lstm(train, batch_size, nb_epoch, neurons):
        # 将数据对中的X, y拆分开,形状为[23*1]
        X, y = train[:, 0:-1], train[:, -1]
        # 将2D数据拼接成3D数据,形状为[23*1*1]
        X = X.reshape(X.shape[0], 1, X.shape[1])
        # Sequential 序贯模型
        model = Sequential()
        # neurons是神经元个数,batch_input_shape是输入形状(样本数,时间步,每个时间步的步长),
        # stateful是状态保留,reset_states是重置网络状态,网络状态和网络权重是两回事
        # 1.同一批数据反复训练很多次,可保留每次训练状态供下次使用
        # 2.不同批数据之间有顺序关联,可保留每次训练状态(一只股票被差分成多个批次)
        # 3.不同批次数据,数据之间没有关联,则不传递网络状态(多只不同股票之间)
        model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True))
        model.add(Dense(1))  # 输出数组为单个数字
        # model.add(Dropout(0.25))  # 随机失活
        # 定义损失函数和优化器
        # compile 训练模式
        # 损失函数(loss):                                     优化器(optimizer):
        # mean_squared_error : 均方误差                         adam : 优化算法
        # mean_absolute_error : 平均绝对误差                    SGD : 随机梯度下降
        # mean_absolute_percentage_error :平均绝对误差百分比     RMSprop
        # mean_squared_logarithmic_error :均方对数误差          Adagrad
        # squared_hinge                                       Adadelta
        # hinge                                               Adamax
        # categorical_hinge                                   Nadam
        # logcosh
        # categorical_crossentropy
        # sparse_categorical_crossentropy
        # binary_crossentropy
        # kullback_leibler_divergence
        # poisson
        # cosine_proximity
        model.compile(loss='mean_squared_error', optimizer='adam')
        for i in range(nb_epoch):
            # model.fit参数:
            # x:输入数据。如果模型只有一个输入,那么x的类型是numpy array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy array
            # y:标签,numpy array
            # batch_size:整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。
            # verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录
            # shuffle:布尔值或字符串,一般为布尔值,表示是否在训练过程中随机打乱输入样本的顺序。若为字符串“batch”,则是用来处理HDF5数据的特殊情况,它将在batch内部将数据打乱。
            # shuffle=False是不混淆数据顺序
            model.fit(X, y, epochs=1, batch_size=batch_size, verbose=1, shuffle=False)
            # 每训练完一个轮回,重置一次网络状态,网络状态和网络权重是两个东西
            model.reset_states()
        model.save('my_model.h5')
        return model
    
    
    def forecast_lstm(model, batch_size, X):
        # 将形状为(1,)的,包含一个元素的一维数组X,构造成形状为(1,1,1)的3D张量
        X = X.reshape(1, 1, len(X))
        # 输出yhat形状为(1,1)的二维数组
        yhat = model.predict(X, batch_size=batch_size)
        # 返回二维数组中,第一行一列的yhat的数值
        return yhat[0, 0]
    
    
    def invert_scale(scaler, X, y):
        # 将x,y转成一个list列表[x,y]->[0.26733207, -0.025524002]
        # [y]可以将一个数值转化成一个单元素列表
        new_row = [x for x in X] + [y]
        # new_row = [X[0]]+[y]
        # 将列表转化为一个,包含两个元素的一维数组,形状为(2,)->[0.26733207 -0.025524002]
        array = numpy.array(new_row)
        print(array.shape)
        # 将一维数组重构成形状为(1,2)的,1行、每行2个元素的,2维数组->[[ 0.26733207 -0.025524002]]
        array = array.reshape(1, len(array))
        # 逆缩放输入的形状为(1,2),输出形状为(1,2) -> [[ 73 15]]
        inverted = scaler.inverse_transform(array)
        return inverted[0, -1]
    
    
    def inverse_difference(history, yhat, interval=1):
        return yhat + history[-interval]
    
    
    # 加载数据
    series = read_csv('data_blue.csv', index_col=0, squeeze=True)
    # 最后N条数据作为测试数据
    testNum = 50
    
    # 将所有数据进行差分转换
    raw_values = series.values
    diff_values = difference(raw_values, 1)
    
    supervised = timeseries_to_supervised(diff_values, 1)
    supervised_values = supervised.values
    
    print(supervised_values)
    
    train, test = supervised_values[0:-testNum], supervised_values[-testNum:]
    
    scaler, train_scaled, test_scaled = scale(train, test)
    
    print(test_scaled)
    
    #单步预测,循环2000次,100个神经元,无dropout,对,我瞎调的。
    lstm_model = fit_lstm(train_scaled, 1, 2000, 100)
    #lstm_model = load_model('my_model.h5')
    
    # print(train_scaled)
    train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
    print(train_reshaped)
    
    lstm_model.predict(train_reshaped, batch_size=1)
    
    predictions = list()
    
    predictions_error = []
    
    for i in range(len(test_scaled)):
        # 将(testNum,2)的2D训练集test_scaled拆分成X,y;
        # 其中X是第i行的0到-1列,形状是(1,)的包含一个元素的一维数组;y是第i行,倒数第1列,是一个数值;
        X, y = test_scaled[i, 0:-1], test_scaled[i, -1]
        # 将训练好的模型lstm_model,X变量,传入预测函数,定义步长为1,
        yhat = forecast_lstm(lstm_model, 1, X)
        print(yhat)
        #print(yhat.shape)
        # 对预测出的y值逆缩放
        yhat = invert_scale(scaler, X, yhat)
        print(yhat)
        # 对预测出的y值逆差分转换
        yhat = inverse_difference(raw_values, yhat, len(test_scaled) + 1 - i)
        print(yhat)
        # 存储预测的y值
        predictions.append(yhat)
        print(yhat)
        # 获取真实的y值
        expected = raw_values[len(train) + i + 1]
        print(expected)
        predictions_error.append(expected-yhat)
        # 输出对比预测值与真实值做
        print('Month=%d, Predicted=%f, Expected=%f' % (i + 1, yhat, expected))
    
    rmse = sqrt(mean_squared_error(raw_values[-testNum:], predictions))
    print('Test RMSE: %.3f' % rmse)
    
    print(predictions_error)
    # 作图展示
    pyplot.plot(raw_values[-testNum:])
    pyplot.plot(predictions)
    #pyplot.show()
    ax = 0
    pyplot.plot(raw_values[-testNum:]-predictions)
    for i in range(testNum):
        ax = ax + abs(predictions[i])
    bx = ax/testNum
    print(bx)
    pyplot.show()
    
    

    我自己有点笔记,忽略就好。

    总之,结论就是:没有任何作用↓,绿线(相差值)走势和蓝线(真实值)几乎都一样了,证明,橙线(预测值)没有任何价值,想要借此发财的洗洗睡吧。
    《基于LSTM神经网络的双色球蓝球数字预测》_第2张图片
    小幻月
    2021年3月9日

  • 你可能感兴趣的:(小幻月的日常笔记,python,深度学习,神经网络,爬虫)