如何用神经网络预测伪随机数?模型仅返回高频数求助
问题分析与解决方案
任务可行性说明
你当前的任务本质上不可行,因为你生成的序列是完全独立的伪随机数:每个数的生成逻辑和前面的序列没有任何关联,属于**独立同分布(i.i.d.)**数据。这种情况下,没有任何可被模型学习的模式,模型能做的最优策略就是预测出现频率最高的类别(也就是0类,占比48%),这就是为什么你的模型只输出0。
问题原因拆解
- 数据无序列相关性:
generate_sequence函数里每个数都是通过randint独立生成的,前20个数和下一个数没有逻辑关联,模型无法找到任何预测线索。 - 不必要的预处理:对离散类别输入使用
tf.keras.utils.normalize没有意义,反而会破坏类别之间的离散特征,干扰模型学习。 - 类别不平衡:0类的生成概率是48%,远高于1类(24%)、2类(16%)、3类(8%)、4类(4%),模型为了追求更高准确率,会自然偏向预测占比最高的类别。
改进方向
1. 调整任务目标(如果想练习序列预测)
如果是为了学习序列预测,需要生成有依赖关系的序列,比如让下一个数和前面的数存在逻辑关联。例如修改生成函数:
def generate_sequence(length=1000000): rList = [] # 初始值 prev = randint(0,4) rList.append(prev) for i in range(1, length): # 简单依赖:下一个数是前一个数+1取模5(可自定义更复杂逻辑) prev = (prev + 1) % 5 rList.append(prev) return rList
这种序列有明确的序列模式,模型可以学习到预测规律。
2. 针对当前代码的优化(仅解决类别不平衡问题)
虽然无法实现真正的预测,但可以调整代码让模型不再只输出最高频类别:
- 移除归一化步骤:离散类别不需要归一化。
- 使用类别权重平衡:在训练时给低频率类别更高的权重,避免模型偏向高频类。
修改后的代码:
from random import randint import numpy as np import tensorflow as tf def generate_sequence(length=1000000): rList = [] for i in range(length): rInt = randint(0, 99) if rInt >= 0 and rInt <= 47: rList.append(0) elif rInt > 47 and rInt <= 71: rList.append(1) elif rInt > 71 and rInt <= 87: rList.append(2) elif rInt > 87 and rInt <= 95: rList.append(3) else: rList.append(4) return rList data = generate_sequence() train_data = data[:800000] test_data = data[800000:] x_train = [] y_train = [] x_test = [] y_test = [] for i in range(0, 799980, 20): x_train.append(train_data[i:i+20]) y_train.append(train_data[i+20]) for i in range(0, 199980, 20): x_test.append(test_data[i:i+20]) y_test.append(test_data[i+20]) # 移除归一化步骤 x_train = np.asarray(x_train) y_train = np.asarray(y_train) x_test = np.asarray(x_test) y_test = np.asarray(y_test) # 计算类别权重:根据每个类别的频率倒数计算 class_counts = np.bincount(y_train) total = len(y_train) class_weights = {i: total / (5 * class_counts[i]) for i in range(5)} model = tf.keras.models.Sequential() model.add(tf.keras.layers.Flatten()) model.add(tf.keras.layers.Dense(625, activation=tf.nn.relu)) model.add(tf.keras.layers.Dense(125, activation=tf.nn.relu)) model.add(tf.keras.layers.Dense(25, activation=tf.nn.relu)) model.add(tf.keras.layers.Dense(5, activation=tf.nn.softmax)) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # 加入class_weight参数 model.fit(x_train, y_train, epochs=5, class_weight=class_weights) val_loss, val_acc = model.evaluate(x_test, y_test) print(val_loss, val_acc) prediction = model.predict(x_test) for pred in prediction: print(np.argmax(pred))
3. 序列模型适配(仅当数据有依赖时有用)
如果使用有依赖的序列,建议改用循环神经网络(如LSTM)来处理序列输入,示例结构:
model = tf.keras.models.Sequential() # 调整输入形状为(序列长度, 特征数),这里每个时间步是1个特征 model.add(tf.keras.layers.LSTM(64, input_shape=(20, 1))) model.add(tf.keras.layers.Dense(32, activation='relu')) model.add(tf.keras.layers.Dense(5, activation='softmax')) # 注意:输入需要调整形状为(样本数, 20, 1) x_train = x_train.reshape(-1, 20, 1) x_test = x_test.reshape(-1, 20, 1)
内容的提问来源于stack exchange,提问作者SOME_LIMES
相关产品推荐
相关产品推荐

