मैट्रिक्स के स्तंभों के बीच रैखिक निर्भरता के लिए परीक्षण


26

मेरे पास सुरक्षा रिटर्न का सहसंबंध मैट्रिक्स है जिसका निर्धारक शून्य है। (नमूना सहसंबंध मैट्रिक्स के बाद से यह थोड़ा आश्चर्यजनक है और संबंधित सहसंयोजक मैट्रिक्स सैद्धांतिक रूप से सकारात्मक होना चाहिए।)

मेरी परिकल्पना यह है कि कम से कम एक सुरक्षा अन्य प्रतिभूतियों पर रैखिक रूप से निर्भर है। आर में एक फ़ंक्शन है जो क्रमिक रूप से प्रत्येक स्तंभ को रैखिक निर्भरता के लिए एक मैट्रिक्स का परीक्षण करता है?

उदाहरण के लिए, एक दृष्टिकोण एक समय में एक सहसंबंध मैट्रिक्स एक सुरक्षा का निर्माण करना होगा और प्रत्येक चरण पर निर्धारक की गणना करना होगा। जब निर्धारक = 0 तब रुक जाते हैं क्योंकि आपने सुरक्षा की पहचान कर ली है जो अन्य प्रतिभूतियों का रैखिक संयोजन है।

ऐसे मैट्रिक्स में रैखिक निर्भरता की पहचान करने के लिए किसी भी अन्य तकनीक की सराहना की जाती है।


आपका मैट्रिक्स सकारात्मक अर्ध-निश्चित है, हालांकि यह सकारात्मक नहीं है, क्योंकि यह एकवचन है।
ttnphns 17

आयाम क्या हैं (नहीं? चर? नहीं नमूने।)
कार्ल

स्तंभों की संख्या = 480. प्रत्येक समय श्रृंखला के लिए पंक्तियों की संख्या = 502. सामान्य तौर पर आप पाते हैं कि नमूना covariance मैट्रिक्स के बड़े समय की श्रृंखला सकारात्मक निश्चित होती है। हालांकि, ऐसे कई मामले हैं जहां आप हाल के बाजार की स्थितियों को प्रतिबिंबित करने के लिए टी (या घातीय वजन) के काफी छोटे मूल्य का उपयोग करना चाहते हैं।
राम अहलूवालिया

3
प्रश्न बीमार है। यदि आपका डेटा मैट्रिक्स 502 से 480 है तो यह कहना कि मैट्रिक्स की रैंक (मैट्रिक्स के कॉलम स्पेस में आयाम ) गणितीय रूप से यह कहने के बराबर है कि कुछ कॉलम दूसरों के रैखिक संयोजन है, लेकिन आप कर सकते हैं 'एक कॉलम को बाहर निकालें और कहें कि यह वह कॉलम है जो रैखिक रूप से निर्भर है। इसलिए ऐसा करने के लिए कोई प्रक्रिया नहीं है, और सुझाई गई प्रक्रिया उनके द्वारा शामिल किए गए आदेश के आधार पर काफी मनमानी सुरक्षा उठाएगी। q < 480q<480q<480
NRH

सहसंयोजक मैट्रिक्स सममित है। यह स्थानान्तरण (ए) * ए से उत्पन्न होता है। मैट्रिक्स ए में आयाम 480x502 है। हालाँकि सहसंयोजक मैट्रिक्स 480x480 है
राम अहलूवालिया

जवाबों:


6

आप वास्तव में एक भयावह प्रश्न पूछते हैं: कैसे पता लगाया जाए, एक विलक्षण सहसंबंध (या सह-वर्ग, या सम-वर्ग-और-क्रॉस-उत्पाद) मैट्रिक्स को देखते हुए, कौन सा स्तंभ रैखिक रूप से किस पर निर्भर है। मुझे लगता है कि स्वीप ऑपरेशन मदद कर सकता है। यहाँ एसपीएसएस में मेरी जांच है (आर नहीं)।

चलो कुछ डेटा उत्पन्न करते हैं:

        v1        v2        v3         v4          v5
    -1.64454    .35119   -.06384    -1.05188     .25192
    -1.78520   -.21598   1.20315      .40267    1.14790
     1.36357   -.96107   -.46651      .92889   -1.38072
     -.31455   -.74937   1.17505     1.27623   -1.04640
     -.31795    .85860    .10061      .00145     .39644
     -.97010    .19129   2.43890     -.83642    -.13250
     -.66439    .29267   1.20405      .90068   -1.78066
      .87025   -.89018   -.99386    -1.80001     .42768
    -1.96219   -.27535    .58754      .34556     .12587
    -1.03638   -.24645   -.11083      .07013    -.84446

चलो V2, V4 और V5 के बीच कुछ रैखिक निर्भरता बनाते हैं:

compute V4 = .4*V2+1.2*V5.
execute.

इसलिए, हमने अपने कॉलम V4 को संशोधित किया।

matrix.
get X. /*take the data*/
compute M = sscp(X). /*SSCP matrix, X'X; it is singular*/
print rank(M). /*with rank 5-1=4, because there's 1 group of interdependent columns*/
loop i= 1 to 5. /*Start iterative sweep operation on M from column 1 to column 5*/
-compute M = sweep(M,i).
-print M. /*That's printout we want to trace*/
end loop.
end matrix.

5 पुनरावृत्तियों में एम के प्रिंटआउट:

M
     .06660028    -.12645565    -.54275426    -.19692972    -.12195621
     .12645565    3.20350385    -.08946808    2.84946215    1.30671718
     .54275426    -.08946808    7.38023317   -3.51467361   -2.89907198
     .19692972    2.84946215   -3.51467361   13.88671851   10.62244471
     .12195621    1.30671718   -2.89907198   10.62244471    8.41646486

M
     .07159201     .03947417    -.54628594    -.08444957    -.07037464
     .03947417     .31215820    -.02792819     .88948298     .40790248
     .54628594     .02792819    7.37773449   -3.43509328   -2.86257773
     .08444957    -.88948298   -3.43509328   11.35217042    9.46014202
     .07037464    -.40790248   -2.86257773    9.46014202    7.88345168

M
    .112041875    .041542117    .074045215   -.338801789   -.282334825
    .041542117    .312263922    .003785470    .876479537    .397066281
    .074045215    .003785470    .135542964   -.465602725   -.388002270
    .338801789   -.876479537    .465602725   9.752781632   8.127318027
    .282334825   -.397066281    .388002270   8.127318027   6.772765022

M
   .1238115070   .0110941027   .0902197842   .0347389906   .0000000000
   .0110941027   .3910328733  -.0380581058  -.0898696977  -.3333333333
   .0902197842  -.0380581058   .1577710733   .0477405054   .0000000000
   .0347389906  -.0898696977   .0477405054   .1025348498   .8333333333
   .0000000000   .3333333333   .0000000000  -.8333333333   .0000000000

M
   .1238115070   .0110941027   .0902197842   .0347389906   .0000000000
   .0110941027   .3910328733  -.0380581058  -.0898696977   .0000000000
   .0902197842  -.0380581058   .1577710733   .0477405054   .0000000000
   .0347389906  -.0898696977   .0477405054   .1025348498   .0000000000
   .0000000000   .0000000000   .0000000000   .0000000000   .0000000000

ध्यान दें कि अंततः कॉलम 5 शून्य से भरा हुआ था। इसका मतलब है (जैसा कि मैं इसे समझता हूं) कि वी 5 को कुछ पूर्ववर्ती स्तंभों के साथ रैखिक रूप से बांधा गया है । कौन सा कॉलम? पुनरावृत्ति को देखें जहां स्तंभ 5 अंतिम बार शून्य से भरा नहीं है - पुनरावृत्ति 4. हम वहां देखते हैं कि V5 को V2 और V4 के साथ गुणांक -333 और .8333 के साथ बांधा गया है: V5 = -.3333 * V2 + .8333 * V4, जो मेल खाती है। हमने डेटा के साथ क्या किया है: V4 = .4 * V2 + 1.2 * V5।

यही कारण है कि हम जानते थे कि कौन सा कॉलम रैखिक रूप से किस अन्य के साथ बंधा हुआ है। मैंने यह नहीं जांचा कि डेटा में अन्योन्याश्रितियों के कई समूहों के साथ सामान्य स्थिति में उपरोक्त दृष्टिकोण कितना उपयोगी है। उपरोक्त उदाहरण में यह मददगार दिखाई दिया, हालांकि।


क्या यह कम रो इकोलेन फॉर्म नहीं है? यदि हां, तो आर में उपलब्ध पैकेज / फ़ंक्शन नहीं हैं?
अरुण

@ अरुन, मैं आर उपयोगकर्ता नहीं हूँ इसलिए पता नहीं चल सकता।
ttnphns

25

यहाँ एक सीधा तरीका है: मैट्रिक्स की रैंक की गणना करें, जिसके परिणामस्वरूप प्रत्येक कॉलम को हटा दिया जाता है। कॉलम, जिन्हें हटा दिया जाता है, उच्चतम रैंक में परिणाम रैखिक रूप से निर्भर होते हैं (क्योंकि हटाने वालों में रैंक में कमी नहीं होती है, जबकि एक रैखिक स्वतंत्र कॉलम को हटाता है)।

आर में:

rankifremoved <- sapply(1:ncol(your.matrix), function (x) qr(your.matrix[,-x])$rank)
which(rankifremoved == max(rankifremoved))

1
एक प्रतिगमन मैट्रिक्स में आपत्तिजनक कॉलम का निर्धारण करने में बेहद उपयोगी उत्तर, जहां मुझे त्रुटि मिली system is exactly singular: U[5,5] = 0 , जो अब मुझे पता है कि कॉलम 5 का मुद्दा था (यह शून्य के स्तंभ के रूप में स्पष्टता के साथ स्पष्ट लगता है!)
मैट वेलर

जेम्स की टिप्पणी में, उन्होंने स्क्रिप्ट पोस्ट की: रैंकिफ़ारेमेड <- sapply (1: ncol (your.matrix), फंक्शन (x) qr (your.matrix [, - x]) $ रैंक) जो (rankifovedoved == मैक्स) Rankifremoved)) मैंने एक मैट्रिक्स पर एक परीक्षण किया, मैं आर के आउटपुट पर जानना चाहूंगा। आउटपुट के कॉलम रैखिक रूप से निर्भर हैं? धन्यवाद!

@ EltonAraújo: आउटपुट एक वेक्टर होगा जो रैखिक रूप से निर्भर स्तंभों के सूचकांकों को देगा: इसलिए (2,4,5) ttnphns के उत्तर में उदाहरण के लिए। लेकिन मुझे आश्चर्य है कि संख्यात्मक परिशुद्धता के मुद्दे इस पद्धति को कैसे प्रभावित करने वाले हैं।
Scortchi - को पुनः स्थापित मोनिका

रैंकिफ़्रीमेड में सभी कॉलम होते हैं जो उनके बीच या उनके बीच रैखिक रूप से निर्भर होते हैं। कुछ एप्लिकेशन में, हम एक कॉलम या कुछ कॉलम को बरकरार रखना चाहते हैं और सभी को नहीं छोड़ सकते
MasterJedi

क्या इसके लिए खाली सेट नहीं लौटाना चाहिए your.matrix = matrix(1:4, 2)?
Holger Brandl

15

प्रश्न चर के बीच "अंतर्निहित [रैखिक] रिश्तों की पहचान" के बारे में पूछता है।

रिश्तों का पता लगाने का त्वरित और आसान तरीका यह है कि आप अपने पसंदीदा सॉफ़्टवेयर का उपयोग करके उन चर के खिलाफ किसी भी अन्य चर (एक निरंतर, यहां तक ​​कि) का उपयोग करें: कोई भी अच्छा प्रतिगमन प्रक्रिया का पता लगाएगी और कोलीनियरिटी का निदान करेगी। (आप प्रतिगमन परिणामों को देखने के लिए भी परेशान नहीं होंगे: हम सिर्फ प्रतिगमन मैट्रिक्स की स्थापना और विश्लेषण के एक उपयोगी पक्ष-प्रभाव पर भरोसा कर रहे हैं।)

माना जाता है कि कोलीनियरिटी का पता लगाया जाता है, हालांकि, आगे क्या? प्रिंसिपल कंपोनेंट्स एनालिसिस (पीसीए) वास्तव में वही है जो आवश्यक है: इसके सबसे छोटे घटक निकट-रैखिक संबंधों के अनुरूप हैं। इन संबंधों को सीधे "लोडिंग" से पढ़ा जा सकता है, जो मूल चर के रैखिक संयोजन हैं। छोटे लोडिंग (यानी, छोटे आइजनवेल्स से जुड़े) निकट-कोलीनरीज़ के अनुरूप हैं। का एक स्वदेशी एक परिपूर्ण रैखिक संबंध के अनुरूप होगा। थोड़ा बड़ा ईजेन्यूएल्स जो अभी भी सबसे बड़े से छोटे हैं वे अनुमानित रैखिक संबंधों के अनुरूप होंगे।0

(एक कला है और "लिटिल" लोडिंग क्या है, यह पहचानने के लिए बहुत सारे साहित्य जुड़े हुए हैं। एक आश्रित चर के मॉडलिंग के लिए, मैं पीसीए में स्वतंत्र चर के भीतर इसे शामिल करने का सुझाव दूंगा ताकि घटकों की पहचान की जा सके - चाहे कोई भी हो उनके आकार - जिसमें आश्रित चर महत्वपूर्ण भूमिका निभाता है। इस दृष्टिकोण से, "छोटा" का अर्थ ऐसे किसी भी घटक से बहुत छोटा है। "


आइए कुछ उदाहरण देखें। (ये Rगणना और प्लॉटिंग के लिए उपयोग करते हैं।) पीसीए प्रदर्शन करने के लिए एक फ़ंक्शन के साथ शुरू करें, छोटे घटकों की तलाश करें, उन्हें प्लॉट करें और उनके बीच रैखिक संबंधों को लौटाएं।

pca <- function(x, threshold, ...) {
  fit <- princomp(x)
  #
  # Compute the relations among "small" components.
  #
  if(missing(threshold)) threshold <- max(fit$sdev) / ncol(x)
  i <- which(fit$sdev < threshold)
  relations <- fit$loadings[, i, drop=FALSE]
  relations <- round(t(t(relations) / apply(relations, 2, max)), digits=2)
  #
  # Plot the loadings, highlighting those for the small components.
  #
  matplot(x, pch=1, cex=.8, col="Gray", xlab="Observation", ylab="Value", ...)
  suppressWarnings(matplot(x %*% relations, pch=19, col="#e0404080", add=TRUE))

  return(t(relations))
}

बी,सी,डी,

process <- function(z, beta, sd, ...) {
  x <- z %*% beta; colnames(x) <- "A"
  pca(cbind(x, z + rnorm(length(x), sd=sd)), ...)
}

बी,...,=बी+सी+डी+=बी+(सी+डी)/2+sweep

n.obs <- 80 # Number of cases
n.vars <- 4 # Number of independent variables
set.seed(17)
z <- matrix(rnorm(n.obs*(n.vars)), ncol=n.vars)
z.mean <- apply(z, 2, mean)
z <- sweep(z, 2, z.mean)
colnames(z) <- c("B","C","D","E") # Optional; modify to match `n.vars` in length

बी,...,

परिणाम

ऊपरी बाएं पैनल से जुड़ा आउटपुट था

       A  B  C  D  E
Comp.5 1 -1 -1 -1 -1

00-बी-सी-डी-

ऊपरी मध्य पैनल के लिए आउटपुट था

       A     B     C     D     E
Comp.5 1 -0.95 -1.03 -0.98 -1.02

(,बी,सी,डी,)

       A     B     C     D     E
Comp.5 1 -1.33 -0.77 -0.74 -1.07

'=बी'+सी'+डी'+'

1,1/2,1/2,1

व्यवहार में, यह अक्सर ऐसा नहीं होता है कि एक चर को दूसरों के एक स्पष्ट संयोजन के रूप में एकल किया जाता है: सभी गुणांक तुलनात्मक आकार और भिन्न संकेतों के हो सकते हैं। इसके अलावा, जब संबंधों के एक से अधिक आयाम होते हैं, तो उन्हें निर्दिष्ट करने का कोई अनूठा तरीका नहीं है: उन संबंधों के लिए एक उपयोगी आधार की पहचान करने के लिए आगे के विश्लेषण (जैसे पंक्ति में कमी) की आवश्यकता होती है। यह है कि दुनिया कैसे काम करती है: आप सभी कह सकते हैं कि ये विशेष संयोजन जो पीसीए द्वारा आउटपुट हैं, डेटा में लगभग भिन्नता के अनुरूप नहीं हैं। इससे निपटने के लिए, कुछ लोग प्रतिगमन या उसके बाद के विश्लेषण में स्वतंत्र चर के रूप में सबसे बड़े ("प्रिंसिपल") घटकों का उपयोग करते हैं, जो भी रूप ले सकता है। यदि आप ऐसा करते हैं, तो चर के सेट से आश्रित चर को हटाने और पीसीए को फिर से करने के लिए पहले मत भूलना!


इस आंकड़े को पुन: पेश करने के लिए कोड है:

par(mfrow=c(2,3))
beta <- c(1,1,1,1) # Also can be a matrix with `n.obs` rows: try it!
process(z, beta, sd=0, main="A=B+C+D+E; No error")
process(z, beta, sd=1/10, main="A=B+C+D+E; Small error")
process(z, beta, sd=1/3, threshold=2/3, main="A=B+C+D+E; Large error")

beta <- c(1,1/2,1/2,1)
process(z, beta, sd=0, main="A=B+(C+D)/2+E; No error")
process(z, beta, sd=1/10, main="A=B+(C+D)/2+E; Small error")
process(z, beta, sd=1/3, threshold=2/3, main="A=B+(C+D)/2+E; Large error")

(मुझे सिर्फ एक घटक को प्रदर्शित करने के लिए बड़े-त्रुटि मामलों में थ्रेशोल्ड के साथ फिडेल करना पड़ा: यही कारण है कि इस मान को एक पैरामीटर के रूप में आपूर्ति करने का कारण है process।)


उपयोगकर्ता tnnphns ने कृपया हमारे ध्यान को बारीकी से संबंधित धागे पर निर्देशित किया है। इसका एक उत्तर (जेएम द्वारा) यहां वर्णित दृष्टिकोण का सुझाव देता है।


वाह, आपकी प्रतिक्रिया से मुझे क्या समझ में आता है .. किसी भी अन्य चर के खिलाफ मेरे चर को सीमित करें। वीआईएफ का उपयोग तब आईडी से संबंधित चर..इस काम करता है। क्या एक समय में डेटा के विखंडन के साथ ऐसा करना सबसे अच्छा है? यदि आप प्रतिगमन पूर्व का उपयोग करके कॉलिनियरिटी का पता लगाते हैं, तो क्या आप कुछ भी निकालते हैं? .. पीसीए के बारे में मुझे जो समझ में आता है, वह यह है कि आप सबसे बड़े पीसी का उपयोग करते हैं (अधिकांश विचरण को समझाते हुए) जो कि ईजेंवल पर आधारित होते हैं क्योंकि ये सबसे अधिक विचरण को स्पष्ट करते हैं, ये अलग-अलग होते हैं। मूल चर का उपयोग कर डिग्री। Im छोटे लोडिंग के रूप में अनिश्चित है और वे किसके साथ कॉलिनियर कर रहे हैं
सैमुअल

यह उत्तर बताता है कि छोटे घटकों की व्याख्या कैसे करें: वे कोलिनारिटीज का प्रदर्शन करते हैं। हां, यदि आप चाहें तो आप चर के उपसमूह का उपयोग कर सकते हैं। प्रतिगमन विधि सिर्फ कोलिनियरिटी की उपस्थिति का पता लगाने के लिए है, कोलिनर संबंधों की पहचान करने के लिए नहीं: यही पीसीए करता है।
whuber

"loadings," which are linear combinations of the original variablesयह कथन सटीक नहीं लगता है। लोडिंग भविष्यवाणी चर में घटकों के रैखिक संयोजनों का गुणांक है । तो, क्या आपका मतलब ? एक - 1-1
tnnphns

इसके अलावा, क्या मैं आपसे पूछ सकता हूं कि चर के रैखिक रूप से आश्रित सबसेट के नीचे ट्रैकिंग के कार्य में स्वीप ऑपरेशन ( सांख्यिकी.stackexchange.com/a/16391/3277 ) के उपयोग के बारे में आप अपनी राय छोड़ सकते हैं ?
tnnphns

@ttnphns मैंने इस उत्तर को पोस्ट करने से पहले लोडिंग के बारे में बयान को सत्यापित किया। सत्यापन में लिखते हुए एक डिज़ाइन मैट्रिक्स SVD का प्रदर्शन शामिल था । मैट्रिक्स में रैखिक संबंध ("लोडिंग" जैसा कि रिपोर्ट किया गया है ) और कॉलम (भारित) प्रमुख घटक हैं। सबसे छोटे eigenvalues ​​के साथ स्तंभों तक को सीमित करना के आदर्श को छोटा बनाता है , जो वास्तव में हम चाहते हैं। वास्तव में, जहां eigenvalues , के समान कॉलम - जो के कॉलम के स्पष्ट रूप से रैखिक संयोजन हैं , जैसा कि कहा गया है - सभी शून्य हैं।एक्स = यू डब्ल्यू वीएक्स वीएक्सवी=यूडब्ल्यूडब्ल्यूयूडब्ल्यू0एक्सवीएक्सएक्स=यूडब्ल्यूवी'वीprincompएक्सवी=यूडब्ल्यूडब्ल्यूयूडब्ल्यू0एक्सवीएक्स
whuber


3

मैं इस मुद्दे पर लगभग दो हफ्ते पहले भाग गया और फैसला किया कि मुझे इसे फिर से तैयार करने की आवश्यकता है क्योंकि जब बड़े पैमाने पर डेटा सेट के साथ काम किया जाता है, तो इन चीजों को मैन्युअल रूप से करना असंभव है।

मैंने एक () लूप बनाया है जो मैट्रिक्स के रैंक की गणना एक बार में करता है। तो पहली पुनरावृत्ति के लिए, रैंक 1 होगी। दूसरा, 2. यह तब तक होता है जब तक कि रैंक आपके द्वारा उपयोग किए जा रहे कॉलम नंबर से कम नहीं हो जाती।

बहुत सीधा:

for (i in 1:47) {

  print(qr(data.frame[1:i])$rank) 
  print(i) 
  print(colnames(data.frame)[i])
  print("###") 
}

() लूप ब्रेकडाउन

  1. ith कॉलम के लिए रैंक की गणना करता है
  2. पुनरावृति संख्या प्रिंट करता है
  3. संदर्भ के लिए कॉलम नाम प्रिंट करता है
  4. कंसोल को "###" से विभाजित करता है ताकि आप आसानी से स्क्रॉल कर सकें

मुझे यकीन है कि आप एक स्टेटमेंट जोड़ सकते हैं, मुझे इसकी आवश्यकता नहीं है क्योंकि मैं केवल 50ish कॉलम के साथ काम कर रहा हूं।

उम्मीद है की यह मदद करेगा!


2
हालांकि इस सैद्धांतिक रूप से कुछ भी गलत नहीं है, यह संख्यात्मक रूप से अस्थिर और अक्षम एल्गोरिथ्म है। विशेष रूप से बड़ी संख्या में स्तंभों के साथ, यह निकट-समरूपता का पता लगाने में विफल हो सकता है और मिथ्यात्व का पता लगा सकता है जहां कोई भी मौजूद नहीं है।
whuber

2

मैट्रिक्स का रैंक, मैट्रिक्स का रैखिक = स्वतंत्र स्तंभों (या पंक्तियों) की संख्या। एक के लिए n द्वारा n मैट्रिक्स एक , रैंक (ए) = n => सभी कॉलम (या पंक्तियाँ) रैखिक स्वतंत्र हैं।


2

ऐसा नहीं है कि इस उत्तर का जवाब कुछ हद तक दिया जा सकता है, लेकिन मुझे लगा कि मैं गणित का संक्षिप्त विवरण दूंगा।

एक्स'एक्सv=0v0vएक्स'एक्सλ=0एक्स'एक्सएक्सएक्स'एक्सλ=0एक्स'एक्सvλ

κj=λमीटरएक्सλj

एक्स'एक्स=[0.0010000.0010000.001]
λ1=λ2=λ3=0.001
κ=λमीटरएक्सλमीटरमैंn=1

उद्धरण

मॉन्टगोमरी, डी। (2012)। रैखिक प्रतिगमन विश्लेषण, 5 वें संस्करण का परिचय। जॉन विले एंड संस इंक।


1
एक्स

क्यूआरएक्सnकश्मीरn>>कश्मीरएक्सआर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.