Làm thế nào để có được kết quả có thể lặp lại trong keras


79

Tôi nhận được các kết quả khác nhau (kiểm tra độ chính xác) mỗi khi tôi chạy imdb_lstm.pyví dụ từ khung Keras ( https://github.com/fchollet/keras/blob/master/examples/imdb_lstm.py ) Mã chứa np.random.seed(1337)ở trên cùng, trước bất kỳ keras nào hàng nhập khẩu. Nó sẽ ngăn nó tạo ra các số khác nhau cho mỗi lần chạy. Tôi đang thiếu gì?

CẬP NHẬT: Cách repro:

  1. Cài đặt Keras ( http://keras.io/ )
  2. Thực thi https://github.com/fchollet/keras/blob/master/examples/imdb_lstm.py một vài lần. Nó sẽ huấn luyện mô hình và độ chính xác của kiểm tra đầu ra.
    Kết quả mong đợi: Độ chính xác của bài kiểm tra là như nhau trên mọi lần chạy.
    Kết quả thực tế: Độ chính xác của thử nghiệm là khác nhau trên mỗi lần chạy.

CẬP NHẬT2: Tôi đang chạy nó trên Windows 8.1 với MinGW / msys, phiên bản mô-đun:
theano 0.7.0
numpy 1.8.1
scipy 0.14.0c1

CẬP NHẬT 3: Tôi đã thu hẹp vấn đề xuống một chút. Nếu tôi chạy ví dụ với GPU (đặt cờ theano thiết bị = gpu0) thì tôi nhận được độ chính xác kiểm tra khác nhau mỗi lần, nhưng nếu tôi chạy trên CPU thì mọi thứ hoạt động như mong đợi. Cạc đồ họa của tôi: NVIDIA GeForce GT 635)


Tôi không thể tái tạo chạy mã trên ubuntu 14.04
Padraic Cunningham

theano -> 0.6.0, numpy -> '1.9.2',scipy -> '0.15.1'
Padraic Cunningham

Có thể vấn đề là tôi sử dụng Windows. numpy.random.uniform hoạt động tốt, luôn tạo ra kết quả tương tự.
Pavel Surmenok

4
Mã cho GPU phải sử dụng các SIMDhướng dẫn giống như vậy rất nhiều. Điều này có thể dẫn đến trình tạo ngẫu nhiên được gọi theo thứ tự ngẫu nhiên. Ngoài ra, GPU là một thực thể tự trị và nó có thể sử dụng bộ tạo ngẫu nhiên của riêng mình. Rốt cuộc, việc chạy bất kỳ mã nào bạn muốn trên GPU không phải là điều tầm thường.
u354356007 15/09/15

2
Bạn đã sử dụng phiên bản CUDA nào? Bạn đã cài đặt cuDNN? Điều thứ hai tôi tin rằng thực hiện một số hy sinh cho tốc độ dẫn đến hành vi không xác định trên gpu. (Nên nhẹ, tôi nghĩ rằng nó đã làm với các hoạt động nguyên tử được tính trên cơ backrprop, nhưng bạn sẽ không nhận được giá trị như nhau mỗi lần.)
user2805751

Câu trả lời:


50

Bạn có thể tìm thấy câu trả lời tại tài liệu Keras: https://keras.io/getting-started/faq/#how-can-i-obtain-reproducible-results-using-keras-during-development .

Tóm lại, để hoàn toàn chắc chắn rằng bạn sẽ nhận được kết quả có thể tái tạo với tập lệnh python của mình trên CPU của một máy tính / máy tính xách tay thì bạn sẽ phải làm như sau:

  1. Đặt PYTHONHASHSEEDbiến môi trường ở một giá trị cố định
  2. Đặt trình pythontạo giả ngẫu nhiên được tích hợp sẵn ở một giá trị cố định
  3. Đặt trình numpytạo giả ngẫu nhiên ở một giá trị cố định
  4. Đặt trình tensorflowtạo giả ngẫu nhiên ở một giá trị cố định
  5. Định cấu hình một tensorflowphiên toàn cầu mới

Theo Kerasliên kết ở trên cùng, mã nguồn tôi đang sử dụng như sau:

# Seed value
# Apparently you may use different seed values at each stage
seed_value= 0

# 1. Set the `PYTHONHASHSEED` environment variable at a fixed value
import os
os.environ['PYTHONHASHSEED']=str(seed_value)

# 2. Set the `python` built-in pseudo-random generator at a fixed value
import random
random.seed(seed_value)

# 3. Set the `numpy` pseudo-random generator at a fixed value
import numpy as np
np.random.seed(seed_value)

# 4. Set the `tensorflow` pseudo-random generator at a fixed value
import tensorflow as tf
tf.random.set_seed(seed_value)
# for later versions: 
# tf.compat.v1.set_random_seed(seed_value)

# 5. Configure a new global `tensorflow` session
from keras import backend as K
session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)
K.set_session(sess)
# for later versions:
# session_conf = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
# sess = tf.compat.v1.Session(graph=tf.compat.v1.get_default_graph(), config=session_conf)
# tf.compat.v1.keras.backend.set_session(sess)

Không cần phải nói rằng bạn không cần phải chỉ định chính xác bất kỳ seedhoặc random_statetại numpy, scikit-learnhoặc tensorflow/ các keraschức năng mà bạn đang sử dụng trong tập lệnh python của mình bởi vì với mã nguồn ở trên, chúng tôi đặt toàn cầu các trình tạo giả ngẫu nhiên của chúng ở một giá trị cố định.


2
Đối với các phiên bản sau của tensorflow, nếu bạn gặp lỗi, hãy sử dụng tf.random.set_random_seed (seed_value)
Kalpit

13

Tài liệu của Theano nói về những khó khăn khi gieo các biến ngẫu nhiên và lý do tại sao chúng tạo ra từng trường hợp biểu đồ bằng trình tạo số ngẫu nhiên của riêng nó.

Việc chia sẻ trình tạo số ngẫu nhiên giữa các trường hợp {{{RandomOp}}} khác nhau gây khó khăn cho việc tạo ra cùng một luồng bất kể các hoạt động khác trong biểu đồ và giữ cho {{{RandomOps}}} bị cô lập. Do đó, mỗi cá thể {{{RandomOp}}} trong biểu đồ sẽ có bộ tạo số ngẫu nhiên riêng của nó. Bộ tạo số ngẫu nhiên đó là một đầu vào cho hàm. Trong cách sử dụng thông thường, chúng tôi sẽ sử dụng các tính năng mới của đầu vào hàm ({{{value}}}, {{{update}}}) để chuyển và cập nhật rng cho mỗi {{{RandomOp}}}. Bằng cách chuyển các RNG làm đầu vào, có thể sử dụng các phương pháp truy cập đầu vào hàm thông thường để truy cập từng rng của {{{RandomOp}}}. Trong cách tiếp cận này, không có cơ chế tồn tại nào để làm việc với trạng thái số ngẫu nhiên kết hợp của toàn bộ đồ thị.

Họ cũng cung cấp các ví dụ về cách gieo tất cả các trình tạo số ngẫu nhiên.

Bạn cũng có thể tạo hạt giống tất cả các biến ngẫu nhiên được phân bổ bởi một đối tượng RandomStreams bằng phương pháp hạt giống của đối tượng đó. Hạt giống này sẽ được sử dụng để tạo hạt giống một bộ tạo số ngẫu nhiên tạm thời, lần lượt nó sẽ tạo hạt giống cho mỗi biến ngẫu nhiên.

>>> srng.seed(902340)  # seeds rv_u and rv_n with different seeds each

11
Nhưng để gieo chúng, chúng ta cần có quyền truy cập vào các đối tượng ngẫu nhiên của theano mà keras sẽ sử dụng. Có thể thực hiện thông qua API keras không?
tối đa

12

Cuối cùng tôi đã nhận được kết quả có thể tái tạo với mã của mình. Đó là sự kết hợp của các câu trả lời mà tôi đã thấy trên web. Điều đầu tiên là làm những gì @alex nói:

  1. Bộ numpy.random.seed ;
  2. Sử dụng PYTHONHASHSEED=0cho Python 3.

Sau đó, bạn phải giải quyết vấn đề được ghi nhận bởi @ user2805751 liên quan đến cuDNN bằng cách gọi mã Keras của bạn với phần bổ sung sau THEANO_FLAGS:

  1. dnn.conv.algo_bwd_filter=deterministic,dnn.conv.algo_bwd_data=deterministic

Và cuối cùng, bạn phải vá cài đặt Theano của mình theo nhận xét này , về cơ bản bao gồm:

  1. thay thế tất cả các cuộc gọi đến *_dev20nhà điều hành bằng phiên bản thông thường của nó trong theano/sandbox/cuda/opt.py.

Điều này sẽ mang lại cho bạn kết quả tương tự cho cùng một hạt giống.

Lưu ý rằng có thể có sự chậm lại. Tôi thấy thời gian chạy tăng khoảng 10%.


6

Vấn đề hiện đã được giải quyết trong Tensorflow 2.0! Tôi đã gặp vấn đề tương tự với TF 1.x (xem Nếu kết quả Keras không thể tái tạo, thì phương pháp tốt nhất để so sánh các mô hình và chọn siêu tham số là gì? )

import os
####*IMPORANT*: Have to do this line *before* importing tensorflow
os.environ['PYTHONHASHSEED']=str(1)

import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.layers 
import random
import pandas as pd
import numpy as np

def reset_random_seeds():
   os.environ['PYTHONHASHSEED']=str(1)
   tf.random.set_seed(1)
   np.random.seed(1)
   random.seed(1)

#make some random data
reset_random_seeds()
NUM_ROWS = 1000
NUM_FEATURES = 10
random_data = np.random.normal(size=(NUM_ROWS, NUM_FEATURES))
df = pd.DataFrame(data=random_data, columns=['x_' + str(ii) for ii in range(NUM_FEATURES)])
y = df.sum(axis=1) + np.random.normal(size=(NUM_ROWS))

def run(x, y):
    reset_random_seeds()

    model = keras.Sequential([
            keras.layers.Dense(40, input_dim=df.shape[1], activation='relu'),
            keras.layers.Dense(20, activation='relu'),
            keras.layers.Dense(10, activation='relu'),
            keras.layers.Dense(1, activation='linear')
        ])
    NUM_EPOCHS = 500
    model.compile(optimizer='adam', loss='mean_squared_error')
    model.fit(x, y, epochs=NUM_EPOCHS, verbose=0)
    predictions = model.predict(x).flatten()
    loss = model.evaluate(x,  y) #This prints out the loss by side-effect

#With Tensorflow 2.0 this is now reproducible! 
run(df, y)
run(df, y)
run(df, y)

2

Tôi muốn thêm một cái gì đó vào các câu trả lời trước. Nếu bạn sử dụng python 3 và bạn muốn nhận được kết quả có thể lặp lại cho mỗi lần chạy, bạn phải

  1. đặt numpy.random.seed ở đầu mã của bạn
  2. cung cấp PYTHONHASHSEED = 0 làm tham số cho trình thông dịch python

2

Tôi đã đào tạo và thử nghiệm Sequential()loại mạng nơ-ron bằng Keras. Tôi đã thực hiện hồi quy không tuyến tính trên dữ liệu tiếng nói ồn ào. Tôi đã sử dụng mã sau để tạo hạt giống ngẫu nhiên:

import numpy as np
seed = 7
np.random.seed(seed)

Tôi nhận được kết quả chính xác giống nhau của val_lossmỗi lần tôi đào tạo và kiểm tra trên cùng một dữ liệu.


1
Bạn đã sử dụng GPU chưa? Phần mềm phụ trợ nào: Theano hay TensorFlow?
Pavel Surmenok

Tôi đã sử dụng CPU với chương trình phụ trợ Theano.
tauseef_CuriousGuy

1
Hiểu rồi. CPU cũng hoạt động tốt đối với tôi. Tôi chỉ gặp sự cố khi chạy trên GPU.
Pavel Surmenok

2

Điều này phù hợp với tôi:

SEED = 123456
import os
import random as rn
import numpy as np
from tensorflow import set_random_seed

os.environ['PYTHONHASHSEED']=str(SEED)
np.random.seed(SEED)
set_random_seed(SEED)
rn.seed(SEED)

1

Trong Tensorflow 2.0, bạn có thể đặt hạt giống ngẫu nhiên như sau:

import tensorflow as tf
tf.random.set_seed(221)


from tensorflow import keras
from tensorflow.keras import layers


model = keras.Sequential( [ 
layers.Dense(2,name = 'one'),
layers.Dense(3,activation = 'sigmoid', name = 'two'),
layers.Dense(2,name = 'three')])

x = tf.random.uniform((12,12))
model(x)

0

Tôi đồng ý với nhận xét trước đó, nhưng kết quả có thể tái tạo đôi khi cần cùng một môi trường (ví dụ: các gói đã cài đặt, đặc tính của máy, v.v.). Vì vậy, tôi khuyên bạn nên sao chép môi trường của bạn sang nơi khác trong trường hợp để có kết quả tái tạo. Cố gắng sử dụng một trong những công nghệ tiếp theo:

  1. Docker . Nếu bạn có Linux, điều này rất dễ dàng để di chuyển môi trường của bạn sang nơi khác. Ngoài ra, bạn có thể thử sử dụng DockerHub .
  2. Chất kết dính . Đây là một nền tảng đám mây để tái tạo các thí nghiệm khoa học.
  3. Bao giờ hết . Đây là một nền tảng đám mây khác cho "khoa học có thể tái sử dụng". Xem kho dự án trên Github.

Vấn đề của tôi là tôi không thể nhận được kết quả có thể lặp lại ngay cả trên cùng một môi trường khi tôi chạy huấn luyện hai lần.
Pavel Surmenok

0

Tài liệu hội thảo: Khởi tạo trọng lượng không ngẫu nhiên trong mạng học sâu để xác định lặp lại, ngày xuất bản ngày 5 tháng 6 năm 2019 được trình bày tại Hội nghị quốc tế IEEE lần thứ 10 về Hệ thống, Dịch vụ và Công nghệ đáng tin cậy (DESSERT-19) tại Đại học Leeds Beckett (LBU), Vương quốc Anh , Vương quốc Anh, Ireland và phần Ukraina của IEEE ngày 5-7 tháng 6 năm 2019

https://ieeexplore.ieee.org/document/8770007

chỉ ra cách nhận được kết quả có thể lặp lại bằng cách thực thi các vùng mã quan trọng.

nó đã được mở rộng thành Tạp chí: Chủ nghĩa xác định lặp lại bằng cách sử dụng Khởi tạo trọng lượng không ngẫu nhiên trong thành phố thông minh Các ứng dụng của học sâu xuất bản trong Tạp chí Môi trường thông minh đáng tin cậy trong ấn bản đặc biệt của Thành phố thông minh và sử dụng các giá trị lấp lửng xavier và đạt được cùng độ chính xác với các lớp perceptron nhưng tăng trọng lượng theo một trật tự tuyến tính có thể có lợi cho việc trích xuất quy tắc trong các lớp perceptron.


0

Nó có vẻ dễ dàng hơn. Chỉ đặt cái này, nó hoạt động:

import numpy as np
import tensorflow as tf
import random as python_random

def reset_seeds():
   np.random.seed(123) 
   python_random.seed(123)
   tf.random.set_seed(1234)

reset_seeds() 

Chìa khóa của câu hỏi, RẤT QUAN TRỌNG, là gọi hàm reset_seeds () mọi lúc trước khi chạy mô hình. Làm điều đó, bạn sẽ nhận được kết quả có thể lặp lại khi tôi kiểm tra trong Google Collab.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.