मैं TensorFlow के साथ रोबोट के आगे की गतिज को लागू करना चाहता हूं; मुख्य रूप से स्वचालित भेदभाव प्राप्त करने और इस मॉड्यूल को बड़े नेटवर्क आर्किटेक्चर में प्लग करने के लिए।

सामान्य तौर पर मेरे पास डीएच-पैरामीटर (d, थीटा, a, alpha< द्वारा परिभाषित 4x4 रूपांतरण मैट्रिक्स का एक समूह है। /em>) और संयुक्त कोण q:

[[           cos(theta+q),           -sin(theta+q),           0,             a],
 [sin(theta+q)*cos(alpha), cos(theta+q)*cos(alpha), -sin(alpha), -sin(alpha)*d],
 [sin(theta+q)*sin(alpha), cos(theta+q)*sin(alpha),  cos(alpha),  cos(alpha)*d],
 [                      0,                       0,           0,             1]])

मेरे रोबोट में 10 अलग-अलग जोड़ हैं, सभी क्रमिक रूप से जुड़े हुए हैं। मैंने सोचा कि साइन और कोसाइन की पूर्व-गणना करना स्मार्ट होगा।

q = tf.keras.layers.Input((10,))
sin_q = tf.sin(q)
cos_q = tf.cos(q)

आइए डीएच-पैरामीटर के विशिष्ट सेट (d=0.1055, थीटा=0, a=0 के साथ पहले जोड़ में परिवर्तन को देखें। , अल्फ़ा=0):

m0 = [[cos(q0), -sin(q0), 0,       0],
      [sin(q0),  cos(q0), 0,       0],
            0,       0,   1, 0.10550],
            0,       0,   0,       1]] 

मेरी पहली समस्या यह है कि TensorFlow के साथ ऐसा कुछ कैसे बनाया जाए? numpy में मैं मैट्रिक्स को इनिशियलाइज़ करूँगा और नॉनज़रो वैल्यूज़ को भरूँगा।

m_shape = tf.TensorShape((batch_size,4,4))
m0 = tf.zeros(m_shape)
m0[..., 0, 0] = cos_q[..., 0]
m0[..., 0, 1] = -sin_q[..., 0]
m0[..., 1, 0] = cos_q[..., 0]
m0[..., 1, 1] = sin_q[..., 0]
m0[..., 2, 3] = 0.10550
m0[..., 3, 3] = 1
Error -> 'Tensor' object does not support item assignment

लेकिन Tensorflow टेंसर के लिए असाइनमेंट की अनुमति नहीं देता है। ऐसा लगता है कि जाने का रास्ता tf.stack() के माध्यम से है। मुझे अपने निर्दिष्ट बैच_साइज, स्टैक और रीशेप के समान आकार के वेक्टर बनाने की आवश्यकता नहीं है। (नोट: सामान्य स्थिति में शून्य मान कम होते हैं)

e = tf.ones_like(q[..., 0]) 
m0 = tf.stack([cos_q[..., 0], -sin_q[..., 0], 0*e,       0*e,
               sin_q[..., 0],  cos_q[..., 0], 0*e,       0*e,
                         0*e,            0*e, 1*e, 0.10550*e,
                         0*e,            0*e, 0*e,       1*e], axis=-1)
m0 = tf.keras.layers.Reshape((4, 4))(m0)

क्या यह सही है या TensorFlow में ऐसे सामान्य परिवर्तन करने का कोई बेहतर तरीका है?

अंतिम परिणाम के रूप में मुझे गतिज श्रृंखला के अंत में परिवर्तन में दिलचस्पी है। मैं विभिन्न संयुक्त विन्यास (?, 10) की एक सरणी में रखना चाहता हूं और अंत प्रभावक (?, 4, 4) पर परिवर्तन प्राप्त करना चाहता हूं।

m_end = m0 @ m1 @ m2 @ ... @ m10
forward_net = tf.keras.Model(inputs=[q], outputs=[m_end]
result = forward_net.predict(np.random.random((100, 10)))

यह काम करता है लेकिन यह न तो सुरुचिपूर्ण और न ही तेज़ है। गति मेरी बड़ी समस्या है; numpy में समान कार्यान्वयन 150x तेज है।

मैं गति कैसे सुधार सकता हूं? मैंने सोचा कि TensorFlow को इस तरह के कार्यों में उत्कृष्टता प्राप्त करनी चाहिए।

क्या मुझे इसे मॉडल के रूप में बनाना चाहिए और परिणामों की गणना करने के लिए भविष्यवाणी का उपयोग करना चाहिए; यहां सीखने के लिए कुछ नहीं है, इसलिए मुझे नहीं पता कि क्या उपयोग करना है।

2
scleronomic 21 नवम्बर 2019, 17:08
सवाल फिलहाल बहुत स्पष्ट नहीं है। आपके पास वास्तव में क्या है (क्या टेंसर और आकार) और आप उनमें से क्या प्राप्त करना चाहते हैं? ऐसा लगता है कि पहले दो स्निपेट्स के बीच बहुत कम पत्राचार है (पहले में दो कोण शामिल हैं, alpha और theta+q, जबकि दूसरा कुछ कोणों के लिए Z अक्ष के चारों ओर रोटेशन मैट्रिस बनाने की कोशिश करता प्रतीत होता है। क्या आप sin_q और cos_q से उनके अंतिम दो आयामों में रोटेशन मैट्रिसेस वाले टेंसर पर जाना चाहते हैं (इसलिए आकार को (4, 4) से जोड़ा जाएगा)?
 – 
jdehesa
21 नवम्बर 2019, 19:00

1 उत्तर

यदि आप कोण से 4x4 रोटेशन मैट्रिक्स बनाना चाहते हैं, या कोण के साइन और कोसाइन से, आप इसे इस तरह कर सकते हैं:

import tensorflow as tf

def make_rotation(alpha, axis):
    return make_rotation_sincos(tf.math.sin(alpha), tf.math.cos(alpha), axis)

def make_rotation_sincos(sin, cos, axis):
    axis = axis.strip().lower()
    zeros = tf.zeros_like(sin)
    ones = tf.ones_like(sin)
    if axis == 'x':
        rot = tf.stack([
            tf.stack([ ones, zeros, zeros], -1),
            tf.stack([zeros,   cos,  -sin], -1),
            tf.stack([zeros,   sin,   cos], -1),
        ], -2)
    elif axis == 'y':
        rot = tf.stack([
            tf.stack([  cos, zeros,   sin], -1),
            tf.stack([zeros,  ones, zeros], -1),
            tf.stack([ -sin, zeros,   cos], -1),
        ], -2)
    elif axis == 'z':
        rot = tf.stack([
            tf.stack([  cos,  -sin, zeros], -1),
            tf.stack([  sin,   cos, zeros], -1),
            tf.stack([zeros, zeros,  ones], -1),
        ], -2)
    else:
        raise ValueError('Invalid axis {!r}.'.format(axis))
    last_row = tf.expand_dims(tf.stack([zeros, zeros, zeros], -1), -2)
    last_col = tf.expand_dims(tf.stack([zeros, zeros, zeros, ones], -1), -1)
    return tf.concat([tf.concat([rot, last_row], -2), last_col], -1)

आगे की गतिज श्रृंखला की गणना के बारे में, आप tf.scan. उदाहरण के लिए, प्रारंभिक आकार (?, 10) मानते हुए:

# Make rotation matrices
rots = make_rotation(...)
rots_t = tf.transpose(rots, (1, 0, 2, 3))
out = tf.scan(tf.matmul, rots_t)[-1]
1
jdehesa 21 नवम्बर 2019, 20:45
धन्यवाद। यह निश्चित रूप से क्लीनर दिखता है, लेकिन मेरे मामले में परिवर्तन न केवल समन्वय अक्षों के साथ हैं और इसके अलावा मेरे पास अनुवाद है। क्या स्तरित स्टैकिंग एक स्टैक + रीशेप से अधिक तेज़ है?
 – 
scleronomic
21 नवम्बर 2019, 20:21
1
नहीं, एक स्टैक + रीशेप वास्तव में कम से कम तेज़ होना चाहिए यदि यह चिंता का विषय है (सिद्धांत रूप में तेज़, हालांकि टीएफ ऑपरेशन को कुछ अलग नहीं करने के लिए अनुकूलित कर सकता है)। मैंने इसे यहां स्पष्ट करने की कोशिश की, लेकिन यह भी काम करता है।
 – 
jdehesa
21 नवम्बर 2019, 20:40
मुझे अभी एहसास हुआ कि आपका प्रश्न आगे आईके श्रृंखला की गणना के बारे में भी था, मैंने जोड़ा है कि आप tf.scan के साथ ऐसा कैसे कर सकते हैं।
 – 
jdehesa
21 नवम्बर 2019, 20:45