วิธีที่ดีกว่าในการสลับสองอาร์เรย์ numpy พร้อมเพรียง


239

ฉันมีอาร์เรย์ numpy สองตัวที่มีรูปร่างต่างกัน แต่มีความยาวเท่ากัน (มิตินำหน้า) ฉันต้องการสับเปลี่ยนแต่ละองค์ประกอบเช่นนั้นองค์ประกอบที่เกี่ยวข้องยังคงสอดคล้องกัน - เช่นสับเปลี่ยนพวกเขาพร้อมกันด้วยความเคารพดัชนีชั้นนำของพวกเขา

รหัสนี้ใช้งานได้และแสดงเป้าหมายของฉัน:

def shuffle_in_unison(a, b):
    assert len(a) == len(b)
    shuffled_a = numpy.empty(a.shape, dtype=a.dtype)
    shuffled_b = numpy.empty(b.shape, dtype=b.dtype)
    permutation = numpy.random.permutation(len(a))
    for old_index, new_index in enumerate(permutation):
        shuffled_a[new_index] = a[old_index]
        shuffled_b[new_index] = b[old_index]
    return shuffled_a, shuffled_b

ตัวอย่างเช่น:

>>> a = numpy.asarray([[1, 1], [2, 2], [3, 3]])
>>> b = numpy.asarray([1, 2, 3])
>>> shuffle_in_unison(a, b)
(array([[2, 2],
       [1, 1],
       [3, 3]]), array([2, 1, 3]))

อย่างไรก็ตามสิ่งนี้รู้สึกว่า clunky ไม่มีประสิทธิภาพและช้าและต้องมีการทำสำเนาของอาร์เรย์ - ฉันค่อนข้างจะสับพวกเขาในสถานที่เนื่องจากพวกเขาจะค่อนข้างใหญ่

มีวิธีที่ดีกว่าที่จะไปเกี่ยวกับเรื่องนี้? การดำเนินการที่เร็วขึ้นและการใช้หน่วยความจำต่ำเป็นเป้าหมายหลักของฉัน แต่โค้ดที่สง่างามก็ดีเช่นกัน

อีกความคิดหนึ่งที่ฉันมีคือ:

def shuffle_in_unison_scary(a, b):
    rng_state = numpy.random.get_state()
    numpy.random.shuffle(a)
    numpy.random.set_state(rng_state)
    numpy.random.shuffle(b)

มันใช้งานได้ ... แต่มันน่ากลัวนิดหน่อยเพราะฉันเห็นการรับประกันเล็กน้อยว่ามันจะยังคงทำงานต่อไป - มันดูไม่เหมือนสิ่งที่รับประกันว่าจะมีชีวิตรอดในเวอร์ชั่นที่เป็นก้อน ๆ


9
หกปีต่อมาฉันรู้สึกขบขันและประหลาดใจเมื่อคำถามนี้ได้รับความนิยม และในบิตของความบังเอิญที่น่ารื่นรมย์สำหรับไป 1.10 ฉันมีส่วนคณิตศาสตร์ / rand.Shuffle ห้องสมุดมาตรฐาน การออกแบบของ API ทำให้ง่ายต่อการสลับสองอาร์เรย์ในเวลาเดียวกันและทำเช่นนั้นแม้จะเป็นตัวอย่างในเอกสาร
Josh Bleecher Snyder

คำตอบ:


72

โซลูชัน "น่ากลัว" ของคุณไม่ปรากฏว่าน่ากลัวสำหรับฉัน การเรียกshuffle()สองลำดับของความยาวเท่ากันส่งผลให้มีการเรียกหมายเลขไปยังตัวสร้างหมายเลขสุ่มและสิ่งเหล่านี้เป็นองค์ประกอบ "สุ่ม" เพียงอย่างเดียวในอัลกอริทึมแบบสุ่ม ด้วยการรีเซ็ตสถานะคุณมั่นใจได้ว่าการเรียกไปยังตัวสร้างหมายเลขสุ่มจะให้ผลลัพธ์เดียวกันในการเรียกครั้งที่สองshuffle()ดังนั้นอัลกอริทึมทั้งหมดจะสร้างการเปลี่ยนแปลงแบบเดียวกัน

หากคุณไม่ชอบสิ่งนี้ทางออกที่แตกต่างคือการจัดเก็บข้อมูลของคุณในอาร์เรย์เดียวแทนที่จะเป็นสองต้นตั้งแต่ต้นและสร้างมุมมองสองมุมมองไว้ในอาร์เรย์เดียวนี้เพื่อจำลองสองอาร์เรย์ที่คุณมีในขณะนี้ คุณสามารถใช้อาเรย์เดี่ยวสำหรับการสับและมุมมองเพื่อจุดประสงค์อื่นทั้งหมด

ตัวอย่าง: สมมติว่าอาร์เรย์aและbมีลักษณะเช่นนี้:

a = numpy.array([[[  0.,   1.,   2.],
                  [  3.,   4.,   5.]],

                 [[  6.,   7.,   8.],
                  [  9.,  10.,  11.]],

                 [[ 12.,  13.,  14.],
                  [ 15.,  16.,  17.]]])

b = numpy.array([[ 0.,  1.],
                 [ 2.,  3.],
                 [ 4.,  5.]])

ตอนนี้เราสามารถสร้างอาร์เรย์เดียวที่มีข้อมูลทั้งหมด:

c = numpy.c_[a.reshape(len(a), -1), b.reshape(len(b), -1)]
# array([[  0.,   1.,   2.,   3.,   4.,   5.,   0.,   1.],
#        [  6.,   7.,   8.,   9.,  10.,  11.,   2.,   3.],
#        [ 12.,  13.,  14.,  15.,  16.,  17.,   4.,   5.]])

ตอนนี้เราสร้างมุมมองจำลองต้นฉบับaและb:

a2 = c[:, :a.size//len(a)].reshape(a.shape)
b2 = c[:, a.size//len(a):].reshape(b.shape)

ข้อมูลของa2และร่วมกับb2 เพื่อสับเปลี่ยนอาร์เรย์ทั้งสองพร้อมกันใช้cnumpy.random.shuffle(c)

ในรหัสการผลิตคุณแน่นอนจะพยายามที่จะหลีกเลี่ยงการสร้างเดิมaและbที่ทุกคนและทันทีสร้างc, และa2b2

วิธีการแก้ปัญหานี้สามารถปรับให้เข้ากับกรณีที่aและbมีชนิดที่แตกต่างกัน


Re: วิธีการแก้ปัญหาที่น่ากลัว: ฉันแค่กังวลว่าอาร์เรย์ของรูปร่างที่แตกต่างกัน (อาจ) ให้จำนวนการโทรไปยัง rng ที่แตกต่างกันซึ่งจะทำให้เกิดความแตกต่าง อย่างไรก็ตามฉันคิดว่าคุณถูกต้องว่าพฤติกรรมในปัจจุบันอาจไม่น่าจะเปลี่ยนแปลงและการสอนที่ง่ายมากทำให้การยืนยันพฤติกรรมที่ถูกต้องเป็นเรื่องง่ายมาก ...
Josh Bleecher Snyder

ฉันชอบแนวทางที่แนะนำของคุณและแน่นอนสามารถจัดให้มีและเริ่มต้นชีวิต b เป็นอาร์เรย์คแบบครบวงจร อย่างไรก็ตาม a และ b จะต้องต่อเนื่องกันไม่นานหลังจากสับ (สำหรับการถ่ายโอนไปยัง GPU อย่างมีประสิทธิภาพ) ดังนั้นฉันคิดว่าในกรณีเฉพาะของฉันฉันจะทำสำเนา a และ b ต่อไป :(
Josh Bleecher Snyder

@Josh: โปรดทราบว่าnumpy.random.shuffle()ทำงานกับลำดับที่ไม่แน่นอนที่เปลี่ยนแปลงได้เช่นรายการ Python หรืออาร์เรย์ NumPy รูปร่างของอาร์เรย์ไม่สำคัญเพียงความยาวของลำดับ นี้เป็นอย่างมากไม่น่าจะมีการเปลี่ยนแปลงในความคิดของฉัน
Sven Marnach

ฉันไม่รู้ นั่นทำให้ฉันรู้สึกสบายใจขึ้นมาก ขอบคุณ.
Josh Bleecher Snyder

@SvenMarnach: ฉันโพสต์คำตอบด้านล่าง คุณสามารถแสดงความคิดเห็นว่าคุณคิดว่าเหมาะสมหรือไม่และเป็นวิธีที่ดีในการทำเช่นนั้น?
ajfbiw.s

351

คุณสามารถใช้การจัดทำดัชนีอาร์เรย์ของ NumPy :

def unison_shuffled_copies(a, b):
    assert len(a) == len(b)
    p = numpy.random.permutation(len(a))
    return a[p], b[p]

สิ่งนี้จะส่งผลให้เกิดการสร้างอาร์เรย์พร้อมเพรียงแยกกัน


13
สิ่งนี้จะสร้างสำเนาเนื่องจากใช้การทำดัชนีขั้นสูง แต่แน่นอนว่ามันเร็วกว่าของเดิม
Sven Marnach

1
@mtrw: ความจริงที่ว่าอาร์เรย์ดั้งเดิมไม่ถูกแตะต้องไม่ได้เป็นกฎที่ว่าอาร์เรย์ที่ส่งคืนนั้นเป็นมุมมองของข้อมูลเดียวกัน แต่พวกเขาก็ไม่แน่นอนเนื่องจากมุมมอง NumPy ไม่ยืดหยุ่นพอที่จะสนับสนุนมุมมองที่เปลี่ยนแปลง (สิ่งนี้จะไม่เป็นที่ต้องการ)
Sven Marnach

1
@Sven - ฉันต้องเรียนรู้เกี่ยวกับมุมมองจริงๆ @Dat Chu - ฉันเพิ่งลอง>>> t = timeit.Timer(stmt = "<function>(a,b)", setup = "import numpy as np; a,b = np.arange(4), np.arange(4*20).reshape((4,20))")>>> t.timeit()และมีเวลา 38 วินาทีสำหรับรุ่น OP และ 27.5 วินาทีสำหรับฉันสำหรับการโทร 1 ล้านครั้งต่อครั้ง
mtrw

3
ฉันชอบความเรียบง่ายและความสามารถในการอ่านสิ่งนี้และการจัดทำดัชนีขั้นสูงยังคงทำให้ฉันประหลาดใจและประหลาดใจ เพราะคำตอบนี้พร้อมรับ +1 ถึงแม้ว่าจะเป็นเรื่องแปลกในชุดข้อมูล (ใหญ่) ของฉันมันช้ากว่าฟังก์ชั่นดั้งเดิมของฉัน: ต้นฉบับของฉันใช้เวลา ~ 1.8 วินาทีสำหรับการทำซ้ำ 10 ครั้งและใช้เวลาประมาณ 2.7 วินาที ตัวเลขทั้งสองค่อนข้างสอดคล้องกัน ผมชุดข้อมูลที่ใช้ในการทดสอบได้a.shapeเป็น(31925, 405)และเป็นb.shape (31925,)
Josh Bleecher Snyder

1
บางทีความเชื่องช้าอาจเกี่ยวข้องกับความจริงที่ว่าคุณไม่ได้ทำอะไรในสถานที่ แต่เป็นการสร้างอาร์เรย์ใหม่แทน หรือมีความเชื่องช้าที่เกี่ยวข้องกับวิธีการที่ CPython วิเคราะห์ดัชนีอาร์เรย์
ÍhorMé

174
X = np.array([[1., 0.], [2., 1.], [0., 0.]])
y = np.array([0, 1, 2])
from sklearn.utils import shuffle
X, y = shuffle(X, y, random_state=0)

หากต้องการเรียนรู้เพิ่มเติมดูhttp://scikit-learn.org/stable/modules/generated/sklearn.utils.shuffle.html


1
โซลูชันนี้สร้างสำเนา ( "อาร์เรย์ดั้งเดิมไม่ได้รับผลกระทบ" ) ในขณะที่โซลูชัน "น่ากลัว" ของผู้เขียนไม่ได้
bartolo-otrit

คุณสามารถเลือกสไตล์ที่คุณต้องการ
James

33

ทางออกที่ง่ายมาก:

randomize = np.arange(len(x))
np.random.shuffle(randomize)
x = x[randomize]
y = y[randomize]

สองอาร์เรย์ x, y ตอนนี้ทั้งสองสับแบบสุ่มในลักษณะเดียวกัน


5
นี่เทียบเท่ากับโซลูชันของ mtrw สองบรรทัดแรกของคุณกำลังสร้างการเรียงสับเปลี่ยน แต่สามารถทำได้ในหนึ่งบรรทัด
Josh Bleecher Snyder

19

James เขียนในปี 2558 โซลูชัน sklearn ซึ่งมีประโยชน์ แต่เขาเพิ่มตัวแปรสถานะแบบสุ่มซึ่งไม่จำเป็น ในโค้ดด้านล่างสถานะการสุ่มจาก numpy จะถูกสันนิษฐานโดยอัตโนมัติ

X = np.array([[1., 0.], [2., 1.], [0., 0.]])
y = np.array([0, 1, 2])
from sklearn.utils import shuffle
X, y = shuffle(X, y)

16
from np.random import permutation
from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data #numpy array
y = iris.target #numpy array

# Data is currently unshuffled; we should shuffle 
# each X[i] with its corresponding y[i]
perm = permutation(len(X))
X = X[perm]
y = y[perm]

12

สับเปลี่ยนอาร์เรย์จำนวนใดก็ได้พร้อมกันในสถานที่โดยใช้ NumPy เท่านั้น

import numpy as np


def shuffle_arrays(arrays, set_seed=-1):
    """Shuffles arrays in-place, in the same order, along axis=0

    Parameters:
    -----------
    arrays : List of NumPy arrays.
    set_seed : Seed value if int >= 0, else seed is random.
    """
    assert all(len(arr) == len(arrays[0]) for arr in arrays)
    seed = np.random.randint(0, 2**(32 - 1) - 1) if set_seed < 0 else set_seed

    for arr in arrays:
        rstate = np.random.RandomState(seed)
        rstate.shuffle(arr)

และสามารถใช้งานได้เช่นนี้

a = np.array([1, 2, 3, 4, 5])
b = np.array([10,20,30,40,50])
c = np.array([[1,10,11], [2,20,22], [3,30,33], [4,40,44], [5,50,55]])

shuffle_arrays([a, b, c])

สิ่งที่ควรทราบ:

  • การยืนยันยืนยันว่าอาร์เรย์อินพุตทั้งหมดมีความยาวเท่ากันตามมิติแรก
  • อาร์เรย์มีการสับแบบแทนที่ขนาดตามมิติแรก - ไม่มีการส่งคืน
  • สุ่มเมล็ดภายในช่วง int32 บวก
  • หากจำเป็นต้องสลับแบบเล่นซ้ำสามารถตั้งค่าเมล็ดได้

หลังจากการสลับข้อมูลสามารถแยกโดยใช้np.splitหรืออ้างอิงโดยใช้ส่วนข้อมูล - ขึ้นอยู่กับแอปพลิเคชัน


2
ทางออกที่สวยงามมันใช้งานได้สมบูรณ์แบบสำหรับฉัน แม้จะมีอาร์เรย์ 3 + แกน
wprins

1
นี่คือคำตอบที่ถูกต้อง ไม่มีเหตุผลที่จะใช้โกลบอล np.random เมื่อคุณสามารถผ่านวัตถุสถานะสุ่ม
Erotemic

หนึ่งRandomStateสามารถใช้นอกวง ดูคำตอบ
bartolo-otrit

1
@ bartolo-otrit ทางเลือกที่จะต้องทำในforวงคือว่าจะกำหนดใหม่หรือ reseed รัฐสุ่ม ด้วยจำนวนของอาร์เรย์ที่ถูกส่งผ่านไปยังฟังก์ชันสับที่คาดว่าจะมีขนาดเล็กฉันไม่คาดหวังความแตกต่างของประสิทธิภาพระหว่างทั้งสอง แต่ใช่ rstate สามารถกำหนดได้นอกลูปและทำการ reseeded ภายในลูปในการวนซ้ำแต่ละครั้ง
Isaac B

9

คุณสามารถสร้างอาร์เรย์เช่น:

s = np.arange(0, len(a), 1)

จากนั้นสลับ:

np.random.shuffle(s)

ตอนนี้ใช้สิ่งนี้เป็นอาร์กิวเมนต์ของอาร์เรย์ของคุณ อาร์กิวเมนต์ที่สับแบบเดียวกันจะส่งคืนเวกเตอร์ที่สับแบบเดียวกัน

x_data = x_data[s]
x_label = x_label[s]

นี่เป็นทางออกที่ดีที่สุดและควรเป็นที่ยอมรับ! มันใช้งานได้กับอาร์เรย์ (มากกว่า 2) จำนวนมากในเวลาเดียวกัน ความคิดนั้นง่าย: เพียงแค่สับเปลี่ยนรายการดัชนี [0, 1, 2, ... , n-1] จากนั้นทำดัชนีแถวของอาร์เรย์อีกครั้งด้วยดัชนีแบบสับ ดี!
Basj

5

วิธีหนึ่งในการสับแบบ in-place ที่สามารถทำได้สำหรับรายการที่เชื่อมต่อคือการใช้เมล็ด (มันอาจเป็นแบบสุ่ม) และใช้ numpy.random.shuffle เพื่อทำการสับ

# Set seed to a random number if you want the shuffling to be non-deterministic.
def shuffle(a, b, seed):
   np.random.seed(seed)
   np.random.shuffle(a)
   np.random.seed(seed)
   np.random.shuffle(b)

แค่นั้นแหละ. นี่จะเป็นการสลับทั้ง a และ b ในวิธีเดียวกัน นอกจากนี้ยังทำในสถานที่ซึ่งเป็นข้อดีอยู่เสมอ

แก้ไขอย่าใช้ np.random.seed () ใช้ np.random.RandomState แทน

def shuffle(a, b, seed):
   rand_state = np.random.RandomState(seed)
   rand_state.shuffle(a)
   rand_state.seed(seed)
   rand_state.shuffle(b)

เมื่อเรียกมันจะส่งผ่านเมล็ดใด ๆ เพื่อป้อนสถานะแบบสุ่ม:

a = [1,2,3,4]
b = [11, 22, 33, 44]
shuffle(a, b, 12345)

เอาท์พุท:

>>> a
[1, 4, 2, 3]
>>> b
[11, 44, 22, 33]

แก้ไข: รหัสคงที่เพื่อหว่านเมล็ดสถานะสุ่มอีกครั้ง


รหัสนี้ใช้ไม่ได้ RandomStateเปลี่ยนสถานะในการโทรครั้งแรกและaและbไม่ถูกสับเปลี่ยนในเวลาเดียวกัน
Bruno Klein

@BrunoKlein คุณพูดถูก ฉันแก้ไขโพสต์เพื่อให้มีสถานะสุ่มอีกครั้ง ยิ่งไปกว่านั้นแม้ว่ามันจะไม่พร้อมเพรียงกันในความรู้สึกของทั้งสองรายการที่ถูกสับในเวลาเดียวกัน แต่พวกมันก็พร้อมเพรียงในแง่ที่ว่าทั้งสองถูกสับในลักษณะเดียวกันและมันก็ไม่ต้องการหน่วยความจำมากขึ้น คัดลอกของรายการ (ซึ่ง OP กล่าวถึงในคำถามของเขา)
อดัม Snaider

4

มีฟังก์ชั่นที่รู้จักกันดีที่สามารถจัดการสิ่งนี้:

from sklearn.model_selection import train_test_split
X, _, Y, _ = train_test_split(X,Y, test_size=0.0)

เพียงตั้งค่า test_size เป็น 0 จะหลีกเลี่ยงการแยกและให้ข้อมูลแบบสับ แม้ว่าโดยปกติแล้วจะใช้เพื่อแยกการฝึกอบรมและทดสอบข้อมูล แต่จะสับเปลี่ยนข้อมูลด้วย
จากเอกสาร

แบ่งอาร์เรย์หรือเมทริกซ์เป็นส่วนย่อยของรถไฟแบบสุ่มและทดสอบ

ยูทิลิตี้ด่วนที่ล้อมรอบการตรวจสอบความถูกต้องของอินพุตและถัดไป (ShuffleSplit (). split (X, y)) และแอปพลิเคชันเพื่อป้อนข้อมูลในการโทรครั้งเดียวสำหรับการแยกข้อมูล


ฉันไม่อยากจะเชื่อเลยว่าฉันไม่เคยคิดถึงเรื่องนี้ คำตอบของคุณยอดเยี่ยม
เหงียนยาวลอง

2

สมมติว่าเรามีสองอาร์เรย์: a และ b

a = np.array([[1,2,3],[4,5,6],[7,8,9]])
b = np.array([[9,1,1],[6,6,6],[4,2,0]]) 

ก่อนอื่นเราสามารถรับดัชนีแถวได้โดยอนุญาตมิติแรก

indices = np.random.permutation(a.shape[0])
[1 2 0]

จากนั้นใช้การจัดทำดัชนีขั้นสูง ที่นี่เราใช้ดัชนีเดียวกันเพื่อสลับทั้งสองอาร์เรย์พร้อมกัน

a_shuffled = a[indices[:,np.newaxis], np.arange(a.shape[1])]
b_shuffled = b[indices[:,np.newaxis], np.arange(b.shape[1])]

สิ่งนี้เทียบเท่า

np.take(a, indices, axis=0)
[[4 5 6]
 [7 8 9]
 [1 2 3]]

np.take(b, indices, axis=0)
[[6 6 6]
 [4 2 0]
 [9 1 1]]

ทำไมไม่เพียง [ดัชนี,] หรือข [ดัชนี,]?
Kev

1

หากคุณต้องการหลีกเลี่ยงการคัดลอกอาร์เรย์ฉันอยากจะแนะนำว่าแทนที่จะสร้างรายการการเปลี่ยนแปลงคุณจะผ่านทุกองค์ประกอบในอาร์เรย์และสุ่มสลับไปยังตำแหน่งอื่นในอาร์เรย์

for old_index in len(a):
    new_index = numpy.random.randint(old_index+1)
    a[old_index], a[new_index] = a[new_index], a[old_index]
    b[old_index], b[new_index] = b[new_index], b[old_index]

สิ่งนี้ใช้อัลกอริทึมสับเปลี่ยน Knuth-Fisher-Yates


3
codinghorror.com/blog/2007/12/the-danger-of-naivete.htmlทำให้ฉันระวังที่จะใช้อัลกอริทึมแบบสุ่มของฉัน มันมีส่วนรับผิดชอบในการถามคำถามนี้ :) อย่างไรก็ตามคุณมีสิทธิ์ที่จะชี้ให้เห็นว่าฉันควรพิจารณาใช้อัลกอริทึม Knuth-Fisher-Yates
Josh Bleecher Snyder

เห็นดีฉันได้แก้ไขรหัสตอนนี้ อย่างไรก็ตามฉันคิดว่าความคิดพื้นฐานของการสับแบบ in-place สามารถปรับขนาดได้ตามจำนวนอาเรย์โดยพลการเพื่อหลีกเลี่ยงการทำสำเนา
DaveP

รหัสยังไม่ถูกต้อง (รหัสจะไม่ทำงาน) ที่จะทำให้มันทำงานแทนโดยlen(a) reversed(range(1, len(a)))แต่มันจะไม่มีประสิทธิภาพมากอยู่ดี
Sven Marnach

1

ดูเหมือนว่าจะเป็นทางออกที่ง่ายมาก:

import numpy as np
def shuffle_in_unison(a,b):

    assert len(a)==len(b)
    c = np.arange(len(a))
    np.random.shuffle(c)

    return a[c],b[c]

a =  np.asarray([[1, 1], [2, 2], [3, 3]])
b =  np.asarray([11, 22, 33])

shuffle_in_unison(a,b)
Out[94]: 
(array([[3, 3],
        [2, 2],
        [1, 1]]),
 array([33, 22, 11]))

0

ด้วยตัวอย่างนี่คือสิ่งที่ฉันทำ:

combo = []
for i in range(60000):
    combo.append((images[i], labels[i]))

shuffle(combo)

im = []
lab = []
for c in combo:
    im.append(c[0])
    lab.append(c[1])
images = np.asarray(im)
labels = np.asarray(lab)

1
นี่เทียบเท่าหรือcombo = zip(images, labels); shuffle(combo); im, lab = zip(*combo)ช้ากว่ามาก เนื่องจากคุณกำลังใช้ Numpy แล้ววิธีการแก้ปัญหาได้เร็วขึ้นมาก ๆ จะ zip อาร์เรย์โดยใช้ Numpy สับและเปิดเครื่องรูดอีกครั้งcombo = np.c_[images, labels] images, labels = combo.Tสมมติว่าlabelsและimagesเป็นอาร์เรย์ Numpy หนึ่งมิติที่มีความยาวเท่ากันเริ่มต้นด้วยนี่จะเป็นวิธีแก้ปัญหาที่เร็วที่สุดได้อย่างง่ายดาย หากพวกเขาเป็นหลายมิติดูคำตอบของฉันข้างต้น
Sven Marnach

ตกลงว่าเหมาะสม ขอบคุณ! @SvenMarnach
ajfbiw.s

0

ฉันขยาย python random.shuffle () เพื่อหาเรื่องที่สอง:

def shuffle_together(x, y):
    assert len(x) == len(y)

    for i in reversed(xrange(1, len(x))):
        # pick an element in x[:i+1] with which to exchange x[i]
        j = int(random.random() * (i+1))
        x[i], x[j] = x[j], x[i]
        y[i], y[j] = y[j], y[i]

ด้วยวิธีนี้ฉันสามารถมั่นใจได้ว่าการสับเกิดขึ้นในสถานที่และฟังก์ชั่นไม่ได้ยาวเกินไปหรือซับซ้อน


0

เพียงแค่ใช้ numpy ...

ก่อนอื่นผสานสองอินพุตอาร์เรย์ 1D คือเลเบล (y) และอาร์เรย์ 2 มิติคือ data (x) และสลับกับshuffleวิธีNumPy ในที่สุดก็แยกพวกเขาและกลับมา

import numpy as np

def shuffle_2d(a, b):
    rows= a.shape[0]
    if b.shape != (rows,1):
        b = b.reshape((rows,1))
    S = np.hstack((b,a))
    np.random.shuffle(S)
    b, a  = S[:,0], S[:,1:]
    return a,b

features, samples = 2, 5
x, y = np.random.random((samples, features)), np.arange(samples)
x, y = shuffle_2d(train, test)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.