स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

स्किकिट-लर्न के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड

परिचय

K- मीन्स क्लस्टरिंग सबसे व्यापक रूप से उपयोग किए जाने वाले अनसुनी मशीन लर्निंग एल्गोरिदम में से एक है जो डेटा इंस्टेंस के बीच समानता के आधार पर डेटा के क्लस्टर बनाते हैं।

इस गाइड में, हम पहले यह समझने के लिए एक सरल उदाहरण देखेंगे कि स्किकिट-लर्न का उपयोग करके इसे लागू करने से पहले के-मीन्स एल्गोरिथम कैसे काम करता है। फिर, हम चर्चा करेंगे कि K-मीन्स में क्लस्टर्स (Ks) की संख्या का निर्धारण कैसे करें, और दूरी मेट्रिक्स, विचरण, और K-मीन्स के पेशेवरों और विपक्षों को भी कवर करें।

अभिप्रेरण

निम्नलिखित स्थिति की कल्पना करें। एक दिन, आस-पड़ोस में घूमते हुए, आपने देखा कि 10 सुविधा स्टोर थे और आपको आश्चर्य होने लगा कि कौन से स्टोर समान हैं - एक-दूसरे के करीब। उस प्रश्न का उत्तर देने के तरीकों की खोज करते समय, आप एक दिलचस्प दृष्टिकोण के साथ आए हैं जो स्टोर को मानचित्र पर उनके निर्देशांक के आधार पर समूहों में विभाजित करता है।

उदाहरण के लिए, यदि एक स्टोर 5 किमी पश्चिम और 3 किमी उत्तर में स्थित था - तो आप असाइन करेंगे (5, 3) इसके साथ समन्वय करता है, और इसे एक ग्राफ में प्रदर्शित करता है। आइए इस पहले बिंदु को देखें कि क्या हो रहा है:

import matplotlib.pyplot as plt

plt.title("Store With Coordinates (5, 3)")
plt.scatter(x=5, y=3)

यह सिर्फ पहला बिंदु है, इसलिए हम एक विचार प्राप्त कर सकते हैं कि हम एक स्टोर का प्रतिनिधित्व कैसे कर सकते हैं। मान लें कि हमारे पास एकत्र किए गए 10 स्टोरों में पहले से ही 10 निर्देशांक हैं। उन्हें a . में व्यवस्थित करने के बाद numpy सरणी, हम उनके स्थान भी प्लॉट कर सकते हैं:

import numpy as np

points = np.array([[5, 3], [10, 15], [15, 12], [24, 10], [30, 45], [85, 70], [71, 80], [60, 78], [55, 52],[80, 91]])

xs = points[:,0] 
ys = points[:,1]  

plt.title("10 Stores Coordinates")
plt.scatter(x=xs, y=ys)

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

के-मीन्स एल्गोरिथम को मैन्युअल रूप से कैसे लागू करें

अब हम एक ग्राफ पर 10 स्टोर देख सकते हैं, और मुख्य समस्या यह है कि क्या कोई ऐसा तरीका है जिससे उन्हें निकटता के आधार पर विभिन्न समूहों में विभाजित किया जा सके? ग्राफ़ पर एक त्वरित नज़र डालने से, हम शायद ध्यान देंगे दुकानों के दो समूह - एक नीचे-बाईं ओर निचला बिंदु है, और दूसरा ऊपरी-दाएं बिंदु है। शायद, हम बीच में उन दो बिंदुओं को एक अलग समूह के रूप में भी अलग कर सकते हैं - इसलिए बनाना तीन अलग-अलग समूह.

इस खंड में, हम अंक को मैन्युअल रूप से क्लस्टर करने की प्रक्रिया पर जाएंगे - उन्हें दिए गए समूहों की संख्या में विभाजित करना। इस तरह, हम अनिवार्य रूप से सावधानी से के सभी चरणों को देखेंगे के-मीन्स क्लस्टरिंग एल्गोरिथम. इस खंड के अंत तक, आप K-मीन्स क्लस्टरिंग के दौरान किए गए सभी चरणों की सहज और व्यावहारिक समझ हासिल कर लेंगे। उसके बाद, हम इसे स्किकिट-लर्न को सौंपेंगे।

यह निर्धारित करने का सबसे अच्छा तरीका क्या होगा कि अंकों के दो या तीन समूह हैं? एक आसान तरीका यह होगा कि केवल एक संख्या में समूह चुनें - उदाहरण के लिए, दो - और फिर उस पसंद के आधार पर बिंदुओं को समूहबद्ध करने का प्रयास करें।

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

मान लीजिए कि हमने तय कर लिया है कि वहाँ हैं दो समूह हमारे स्टोर (अंक)। अब, हमें यह समझने का तरीका खोजना होगा कि कौन से बिंदु किस समूह से संबंधित हैं। यह प्रतिनिधित्व करने के लिए एक बिंदु चुनकर किया जा सकता है समूह 1 और एक प्रतिनिधित्व करने के लिए समूह 2. अन्य सभी बिंदुओं से प्रत्येक समूह की दूरी को मापते समय उन बिंदुओं को एक संदर्भ के रूप में उपयोग किया जाएगा।

इस तरह, बिंदु कहो (5, 3) समूह 1 से संबंधित है, और बिंदु (79, 60) समूह 2 के लिए। एक नया बिंदु निर्दिष्ट करने का प्रयास करते समय (6, 3) समूहों के लिए, हमें इसकी दूरी उन दो बिंदुओं तक मापनी होगी। बिंदु के मामले में (6, 3) is करीब को (5, 3), इसलिए यह उस बिंदु द्वारा दर्शाए गए समूह से संबंधित है - समूह 1. इस प्रकार, हम सभी बिंदुओं को संगत समूहों में आसानी से समूहित कर सकते हैं।

इस उदाहरण में, समूहों की संख्या निर्धारित करने के अलावा (समूहों) - हम कुछ बिंदुओं को a . होने के लिए भी चुन रहे हैं संदर्भ प्रत्येक समूह के नए बिंदुओं के लिए दूरी की।

हमारे स्टोर के बीच समानता को समझने का यही सामान्य विचार है। आइए इसे व्यवहार में लाएं - हम पहले दो संदर्भ बिंदुओं को चुन सकते हैं बिना सोचे समझे. संदर्भ बिंदु समूह 1 होगा (5, 3) और संदर्भ बिंदु समूह 2 होगा (10, 15). हम अपने दोनों बिंदुओं का चयन कर सकते हैं numpy सरणी द्वारा [0] और [1] अनुक्रमित करें और उन्हें स्टोर करें g1 (समूह 1) और g2 (समूह 2) चर:

g1 = points[0]
g2 = points[1]

ऐसा करने के बाद, हमें अन्य सभी बिंदुओं से उन संदर्भ बिंदुओं की दूरी की गणना करने की आवश्यकता है। यह एक महत्वपूर्ण प्रश्न उठाता है - उस दूरी को कैसे मापें। हम अनिवार्य रूप से किसी भी दूरी माप का उपयोग कर सकते हैं, लेकिन, इस गाइड के प्रयोजन के लिए, आइए यूक्लिडियन दूरी_ का उपयोग करें।

यह जानना उपयोगी हो सकता है कि यूक्लिडियन दूरी माप पाइथागोरस प्रमेय पर आधारित है:

$$
सी^2 = ए^2 + बी^2
$$

जब एक विमान में बिंदुओं के अनुकूल हो - (a1, b1) और (a2, b2), पिछला सूत्र बन जाता है:

$$
सी^2 = (ए2-ए1)^2 + (बी2-बी1)^2
$$

दूरी . का वर्गमूल होगी c, इसलिए हम सूत्र को इस प्रकार भी लिख सकते हैं:

$$
euclidean_{dist} = sqrt[2][(a2 - a1)^2 + (b2 - b1) ^2)]
$$

नोट: आप बहु-आयामी बिंदुओं के लिए यूक्लिडियन दूरी सूत्र को भी सामान्यीकृत कर सकते हैं। उदाहरण के लिए, त्रि-आयामी अंतरिक्ष में, बिंदुओं के तीन निर्देशांक होते हैं - हमारा सूत्र इसे निम्न तरीके से दर्शाता है:
$$
euclidean_{dist} = sqrt[2][(a2 - a1)^2 + (b2 - b1) ^2 + (c2 - c1) ^2)]
$$
हम जिस स्थान पर काम कर रहे हैं, उसके आयामों की संख्या की परवाह किए बिना उसी सिद्धांत का पालन किया जाता है।

अब तक, हमने समूहों का प्रतिनिधित्व करने के लिए बिंदुओं को चुना है, और हम जानते हैं कि दूरियों की गणना कैसे की जाती है। अब, हमारे एकत्र किए गए प्रत्येक स्टोर पॉइंट को एक समूह को असाइन करके दूरियों और समूहों को एक साथ रखें।

इसे बेहतर ढंग से देखने के लिए, हम तीन सूचियाँ घोषित करेंगे। पहले समूह के अंक स्टोर करने वाला पहला - points_in_g1. समूह 2 से अंक जमा करने वाला दूसरा - points_in_g2, और आखिर का - group, करने के लिए लेबल अंक के रूप में या तो 1 (समूह 1 के अंतर्गत आता है) या 2 (समूह 2 के अंतर्गत आता है):

points_in_g1 = []
points_in_g2 = []
group = []

अब हम अपने बिंदुओं के माध्यम से पुनरावृति कर सकते हैं और उनके और हमारे प्रत्येक समूह संदर्भ के बीच यूक्लिडियन दूरी की गणना कर सकते हैं। प्रत्येक बिंदु होगा करीब दो समूहों में से एक के लिए - कौन सा समूह निकटतम है, इसके आधार पर हम प्रत्येक बिंदु को संबंधित सूची में असाइन करेंगे, साथ ही जोड़ते हुए 1 or 2 को group सूची:

for p in points:
    x1, y1 = p[0], p[1]
    euclidean_distance_g1 = np.sqrt((g1[0] - x1)**2 + (g1[1] - y1)**2)
    euclidean_distance_g2 = np.sqrt((g2[0] - x1)**2 + (g2[1] - y1)**2)
    if euclidean_distance_g1 < euclidean_distance_g2:
        points_in_g1.append(p)
        group.append('1')
    else:
        points_in_g2.append(p)
        group.append('2')

आइए इस पुनरावृत्ति के परिणामों को देखें कि क्या हुआ:

print(f'points_in_g1:{points_in_g1}n 
npoints_in_g2:{points_in_g2}n 
ngroup:{group}')

जिसके परिणामस्वरूप:

points_in_g1:[array([5, 3])]
 
points_in_g2:[array([10, 15]), array([15, 12]), 
              array([24, 10]), array([30, 45]), 
              array([85, 70]), array([71, 80]),
              array([60, 78]), array([55, 52]), 
              array([80, 91])]
 
group:[1, 2, 2, 2, 2, 2, 2, 2, 2, 2] 

हम सीबॉर्न का उपयोग करके, निर्दिष्ट समूहों के आधार पर अलग-अलग रंगों के साथ क्लस्टरिंग परिणाम भी प्लॉट कर सकते हैं scatterplot() साथ group एक के रूप में hue तर्क:

import seaborn as sns

sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

यह स्पष्ट रूप से दिखाई देता है कि केवल हमारा पहला बिंदु समूह 1 को सौंपा गया है, और अन्य सभी बिंदुओं को समूह 2 को सौंपा गया है। यह परिणाम शुरुआत में हमने जो कल्पना की थी, उससे अलग है। हमारे परिणामों और हमारी प्रारंभिक अपेक्षाओं के बीच अंतर को ध्यान में रखते हुए - क्या कोई ऐसा तरीका है जिससे हम इसे बदल सकते हैं? ऐसा लगता है वहाँ है!

एक तरीका यह है कि प्रक्रिया को दोहराएं और समूहों के संदर्भ के लिए विभिन्न बिंदुओं का चयन करें। यह हमारे परिणामों को बदल देगा, उम्मीद है, शुरुआत में हमने जो कल्पना की है, उसके अनुरूप। इस दूसरी बार, हम उन्हें यादृच्छिक रूप से नहीं चुन सकते थे जैसा कि हमने पहले किया था, लेकिन a . प्राप्त करके मतलब हमारे सभी पहले से समूहीकृत बिंदुओं में से। इस तरह, उन नए बिंदुओं को संबंधित समूहों के बीच में रखा जा सकता है।

उदाहरण के लिए, यदि दूसरे समूह में केवल अंक थे (10, 15), (30, 45)। नया केंद्रीय बिंदु होगा (10 + 30)/2 और (15+45)/2 - जो के बराबर है (20, 30).

चूंकि हमने अपने परिणामों को सूचियों में रखा है, हम उन्हें पहले बदल सकते हैं numpy सरणियों, उनके xs, ys का चयन करें और फिर प्राप्त करें मतलब:

g1_center = [np.array(points_in_g1)[:, 0].mean(), np.array(points_in_g1)[:, 1].mean()]
g2_center = [np.array(points_in_g2)[:, 0].mean(), np.array(points_in_g2)[:, 1].mean()]
g1_center, g2_center

सलाह: उपयोग करने का प्रयास करें numpy और जितना संभव हो NumPy सरणियाँ। वे बेहतर प्रदर्शन के लिए अनुकूलित हैं और कई रैखिक बीजगणित संचालन को सरल बनाते हैं। जब भी आप किसी रैखिक बीजगणित की समस्या को हल करने का प्रयास कर रहे हों, तो आपको निश्चित रूप से इस पर एक नज़र डालनी चाहिए numpy दस्तावेज़ यह जाँचने के लिए कि क्या कोई है numpy आपकी समस्या को हल करने के लिए डिज़ाइन किया गया तरीका। मौका है कि वहाँ है!

हमारे नए केंद्र बिंदुओं के साथ प्रक्रिया को दोहराने में मदद करने के लिए, आइए अपने पिछले कोड को एक फ़ंक्शन में बदलें, इसे निष्पादित करें और देखें कि क्या बिंदुओं को समूहीकृत करने में कोई बदलाव आया है:

def assigns_points_to_two_groups(g1_center, g2_center):
    points_in_g1 = []
    points_in_g2 = []
    group = []

    for p in points:
        x1, y1 = p[0], p[1]
        euclidean_distance_g1 = np.sqrt((g1_center[0] - x1)**2 + (g1_center[1] - y1)**2)
        euclidean_distance_g2 = np.sqrt((g2_center[0] - x1)**2 + (g2_center[1] - y1)**2)
        if euclidean_distance_g1 < euclidean_distance_g2:
            points_in_g1.append(p)
            group.append(1)
        else:
            points_in_g2.append(p)
            group.append(2)
    return points_in_g1, points_in_g2, group

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

आइए फ़ंक्शन को कॉल करें और इसके परिणामों को स्टोर करें points_in_g1, points_in_g2, तथा group चर:

points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
points_in_g1, points_in_g2, group

और समूह विभाजन की कल्पना करने के लिए रंगीन बिंदुओं के साथ स्कैटरप्लॉट भी प्लॉट करें:

sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

ऐसा लगता है कि हमारे अंक की क्लस्टरिंग है बेहतर होना. लेकिन फिर भी, ग्राफ़ के बीच में दो बिंदु हैं जिन्हें दोनों समूहों से उनकी निकटता को देखते हुए किसी भी समूह को सौंपा जा सकता है। हमने अब तक जो एल्गोरिथम विकसित किया है, वह उन दोनों बिंदुओं को दूसरे समूह को निर्दिष्ट करता है।

इसका मतलब है कि हम संभवत: Xs और Ys के माध्यम से दो नए केंद्रीय बिंदु बनाकर प्रक्रिया को एक बार फिर दोहरा सकते हैं (केंद्रक) हमारे समूहों के लिए और दूरी के आधार पर उन्हें फिर से असाइन करना।

आइए सेंट्रोइड्स को अपडेट करने के लिए एक फंक्शन भी बनाएं। पूरी प्रक्रिया को अब उस फ़ंक्शन की कई कॉलों में घटाया जा सकता है:

def updates_centroids(points_in_g1, points_in_g2):
    g1_center = np.array(points_in_g1)[:, 0].mean(), np.array(points_in_g1)[:, 1].mean()
    g2_center = np.array(points_in_g2)[:, 0].mean(), np.array(points_in_g2)[:, 1].mean()
    return g1_center, g2_center

g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

ध्यान दें कि इस तीसरे पुनरावृत्ति के बाद, प्रत्येक बिंदु अब अलग-अलग समूहों से संबंधित है। ऐसा लगता है कि परिणाम बेहतर हो रहे हैं - आइए इसे एक बार फिर से करें। अब जा रहे हैं चौथा पुनरावृत्ति हमारे तरीके का:

g1_center, g2_center = updates_centroids(points_in_g1, points_in_g2)
points_in_g1, points_in_g2, group = assigns_points_to_two_groups(g1_center, g2_center)
sns.scatterplot(x=points[:, 0], y=points[:, 1], hue=group)

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

यह चौथी बार हमें मिला वही परिणाम पिछले एक के रूप में। तो ऐसा लगता है कि हमारे अंक अब समूह नहीं बदलेंगे, हमारा परिणाम किसी प्रकार की स्थिरता पर पहुंच गया है - यह एक अपरिवर्तनीय स्थिति में आ गया है, या कन्वर्ज्ड. इसके अलावा, हमारे पास ठीक वैसा ही परिणाम है जैसा हमने 2 समूहों के लिए कल्पना की थी। हम यह भी देख सकते हैं कि क्या यह विभाजन समझ में आता है।

आइए अब तक हमने जो कुछ किया है, उसका संक्षेप में संक्षेप में वर्णन करें। हमने भौगोलिक दृष्टि से अपने 10 स्टोरों को दो खंडों में विभाजित किया है - एक निचले दक्षिण-पश्चिम क्षेत्रों में और अन्य पूर्वोत्तर में। हमारे पास जो पहले से है, उसके अलावा अधिक डेटा एकत्र करना दिलचस्प हो सकता है - राजस्व, ग्राहकों की दैनिक संख्या, और बहुत कुछ। इस तरह हम एक समृद्ध विश्लेषण कर सकते हैं और संभवतः अधिक दिलचस्प परिणाम उत्पन्न कर सकते हैं।

इस तरह के क्लस्टरिंग अध्ययन तब किए जा सकते हैं जब एक पहले से स्थापित ब्रांड एक नया स्टोर खोलने के लिए एक क्षेत्र चुनना चाहता है। उस स्थिति में, स्थान के अलावा और भी कई चरों को ध्यान में रखा जाता है।

के-मीन्स एल्गोरिथम के साथ यह सब क्या करना है?

इन चरणों का पालन करते हुए आपने सोचा होगा कि उन्हें K-मीन्स एल्गोरिथम से क्या लेना-देना है। हमने अब तक जो प्रक्रिया की है, वह है: के-मीन्स एल्गोरिथम. संक्षेप में, हमने समूहों/समूहों की संख्या निर्धारित की है, बेतरतीब ढंग से प्रारंभिक बिंदुओं को चुना है, और प्रत्येक पुनरावृत्ति में अद्यतन सेंट्रोइड्स को तब तक निर्धारित किया है जब तक कि क्लस्टर परिवर्तित नहीं हो जाते। हमने मूल रूप से संपूर्ण एल्गोरिथम को हाथ से निष्पादित किया है - प्रत्येक चरण का सावधानीपूर्वक संचालन।

RSI K के-मीन्स में से आता है समूहों की संख्या जिसे पुनरावृत्ति प्रक्रिया शुरू करने से पहले सेट करने की आवश्यकता है। हमारे मामले में कश्मीर = 2. इस विशेषता को कभी-कभी के रूप में देखा जाता है नकारात्मक अन्य क्लस्टरिंग विधियों को ध्यान में रखते हुए, जैसे कि पदानुक्रमित क्लस्टरिंग, जिसके लिए पहले से निश्चित संख्या में क्लस्टर होने की आवश्यकता नहीं है।

इसके साधनों के प्रयोग से K-साधन भी बन जाता है बाहरी और चरम मूल्यों के प्रति संवेदनशील - वे परिवर्तनशीलता को बढ़ाते हैं और हमारे केन्द्रक के लिए अपनी भूमिका निभाना कठिन बनाते हैं। इसलिए, प्रदर्शन करने की आवश्यकता के प्रति सचेत रहें चरम मूल्य और बाहरी विश्लेषण K-मीन्स एल्गोरिथम का उपयोग करके क्लस्टरिंग करने से पहले।

इसके अलावा, ध्यान दें कि हमारे अंक सीधे भागों में विभाजित थे, क्लस्टर बनाते समय वक्र नहीं होते हैं। यह के-मीन्स एल्गोरिथम का नुकसान भी हो सकता है।

नोट: जब आपको इसे अधिक लचीला और दीर्घवृत्त और अन्य आकृतियों के अनुकूल बनाने की आवश्यकता हो, तो a . का उपयोग करके देखें सामान्यीकृत के-मतलब गाऊसी मिश्रण मॉडल. यह मॉडल अण्डाकार विभाजन समूहों के अनुकूल हो सकता है।

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

अब जब हम K-मीन्स एल्गोरिथम में किए गए सभी चरणों को पढ़ चुके हैं, और इसके सभी पेशेवरों और विपक्षों को समझ गए हैं, तो हम अंत में स्किकिट-लर्न लाइब्रेरी का उपयोग करके K-मीन्स को लागू कर सकते हैं।

K-मीन्स एल्गोरिथम का उपयोग कैसे करें Scikit-जानें

हमारे परिणाम को दोबारा जांचने के लिए, इस प्रक्रिया को फिर से करते हैं, लेकिन अब कोड की 3 पंक्तियों का उपयोग कर रहे हैं sklearn:

from sklearn.cluster import KMeans


kmeans = KMeans(n_clusters=2, random_state=42) 
kmeans.fit(points)
kmeans.labels_

यहां, लेबल हमारे पिछले समूहों के समान हैं। आइए परिणाम को जल्दी से प्लॉट करें:

sns.scatterplot(x = points[:,0], y = points[:,1], hue=kmeans.labels_)

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

परिणामी प्लॉट पिछले खंड के समान है।

सर्वोत्तम प्रथाओं, उद्योग-स्वीकृत मानकों और शामिल चीट शीट के साथ, Git सीखने के लिए व्यावहारिक मार्गदर्शिका देखें। Googling Git कमांड को रोकें और वास्तव में सीखना यह!

नोट: स्किकिट-लर्न का उपयोग करके हमने के-मीन्स एल्गोरिथम का प्रदर्शन कैसे किया है, यह देखने से आपको यह आभास हो सकता है कि यह एक नो-ब्रेनर है और आपको इसके बारे में बहुत अधिक चिंता करने की आवश्यकता नहीं है। जब हम K-मीन्स एल्गोरिथम चरण-दर-चरण पर जाते हैं, तो कोड की केवल 3 पंक्तियाँ पिछले अनुभाग में चर्चा किए गए सभी चरणों को पूरा करती हैं। परंतु, शैतान विवरण में है इस मामले में! यदि आप एल्गोरिथम के सभी चरणों और सीमाओं को नहीं समझते हैं, तो सबसे अधिक संभावना है कि आप उस स्थिति का सामना करेंगे जहां K-मीन्स एल्गोरिथम आपको ऐसे परिणाम देगा जिनकी आप अपेक्षा नहीं कर रहे थे।

स्किकिट-लर्न के साथ, आप K-मीन्स को तेज अभिसरण के लिए इनिशियलाइज़ कर सकते हैं init='k-means++' बहस। व्यापक शब्दों में, के-मीन्स++ अभी भी चुनता है k एक समान वितरण के बाद यादृच्छिक रूप से प्रारंभिक क्लस्टर केंद्र। फिर, प्रत्येक बाद के क्लस्टर केंद्र को शेष डेटा बिंदुओं से चुना जाता है, न कि केवल दूरी माप की गणना करके - बल्कि संभाव्यता का उपयोग करके। प्रायिकता का उपयोग करने से एल्गोरिथम में तेजी आती है और यह बहुत बड़े डेटासेट के साथ काम करते समय मददगार होता है।

कोहनी विधि - समूहों की सर्वोत्तम संख्या का चयन

अब तक सब ठीक है! हमने पॉइंट्स और सेंट्रोइड्स के बीच यूक्लिडियन दूरी के आधार पर 10 स्टोर्स को क्लस्टर किया है। लेकिन ग्राफ़ के बीच में उन दो बिंदुओं के बारे में क्या जो क्लस्टर के लिए थोड़ा कठिन हैं? क्या वे एक अलग समूह भी नहीं बना सकते थे? क्या हमने वास्तव में चुनकर गलती की है K = 2 समूह? शायद हमारे पास वास्तव में था K = 3 समूह? हमारे पास तीन से अधिक समूह भी हो सकते हैं और हमें इसकी जानकारी नहीं है।

यहां पूछा जा रहा सवाल है K-मीन्स में समूहों (K) की संख्या का निर्धारण कैसे करें. उस प्रश्न का उत्तर देने के लिए, हमें यह समझने की आवश्यकता है कि क्या K के भिन्न मान के लिए "बेहतर" क्लस्टर होगा।

इसका पता लगाने का सरल तरीका के विभिन्न मूल्यों के साथ बिंदुओं को समूहीकृत करना है K, के लिए के = 2, के = 3, के = 4, और इसी तरह:

for number_of_clusters in range(1, 11): 
    kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
    kmeans.fit(points) 

लेकिन, अलग-अलग के लिए क्लस्टरिंग पॉइंट्स Ks अकेला पर्याप्त नहीं होगा यह समझने के लिए कि क्या हमने इसके लिए आदर्श मान चुना है K. हमें प्रत्येक के लिए क्लस्टरिंग गुणवत्ता का मूल्यांकन करने का एक तरीका चाहिए K हमने चुना है।

मैन्युअल रूप से गणना करना वर्गों के समूह योग के भीतर (WCSS)

हमारे क्लस्टर किए गए बिंदु एक-दूसरे के कितने करीब हैं, इसका एक माप पेश करने के लिए यहां आदर्श स्थान है। यह अनिवार्य रूप से वर्णन करता है कि कितना झगड़ा हमारे पास एक क्लस्टर के अंदर है। इस उपाय को कहा जाता है वर्गों के समूह योग के भीतरया, डब्ल्यूसीएसएस छोटे के लिए। WCSS जितना छोटा होगा, हमारे अंक उतने ही करीब होंगे, इसलिए हमारे पास एक अधिक सुव्यवस्थित क्लस्टर है। WCSS सूत्र का उपयोग किसी भी संख्या में समूहों के लिए किया जा सकता है:

$$
WCSS = योग (Pi_1 - Centroid_1) ^ 2 + cdots + योग (Pi_n - Centroid_n) ^ 2
$$

नोट: इस गाइड में, हम उपयोग कर रहे हैं यूक्लिडियन दूरी सेंट्रोइड्स प्राप्त करने के लिए, लेकिन अन्य दूरी के उपाय, जैसे मैनहट्टन, का भी उपयोग किया जा सकता है।

अब हम मान सकते हैं कि हमने दो समूहों का चयन किया है और WCSS को बेहतर ढंग से समझने के लिए WCSS को लागू करने का प्रयास किया है और इसका उपयोग कैसे किया जाता है। जैसा कि सूत्र बताता है, हमें सभी क्लस्टर बिंदुओं और सेंट्रोइड्स के बीच वर्ग अंतर को जोड़ना होगा। तो, यदि पहले समूह से हमारा पहला बिंदु है (5, 3) और पहले समूह का हमारा अंतिम केन्द्रक (अभिसरण के बाद) है (16.8, 17.0), WCSS होगा:

$$
WCSS = योग((5,3) – (16.8, 17.0))^2
$$

$$
डब्ल्यूसीएसएस = योग((5-16.8) + (3-17.0))^2
$$

$$
डब्ल्यूसीएसएस = योग((-11.8) + (-14.0))^2
$$

$$
डब्ल्यूसीएसएस = योग((-25.8))^2
$$

$$
डब्ल्यूसीएसएस = 335.24
$$

यह उदाहरण दिखाता है कि हम क्लस्टर से एक बिंदु के लिए WCSS की गणना कैसे करते हैं। लेकिन क्लस्टर में आमतौर पर एक से अधिक बिंदु होते हैं, और हमें WCSS की गणना करते समय उन सभी को ध्यान में रखना होगा। हम ऐसा एक फ़ंक्शन को परिभाषित करके करेंगे जो बिंदुओं और सेंट्रोइड्स का एक समूह प्राप्त करता है, और वर्गों का योग देता है:

def sum_of_squares(cluster, centroid):
    squares = []
    for p in cluster:
        squares.append((p - centroid)**2)
        ss = np.array(squares).sum()
    return ss

अब हम प्रत्येक क्लस्टर के लिए वर्गों का योग प्राप्त कर सकते हैं:

g1 = sum_of_squares(points_in_g1, g1_center)
g2 = sum_of_squares(points_in_g2, g2_center)

और कुल प्राप्त करने के लिए परिणामों का योग करें डब्ल्यूसीएसएस:

g1 + g2

इसका परिणाम यह होगा:

2964.3999999999996

तो, हमारे मामले में, जब K 2 के बराबर है, कुल WCSS है 2964.39. अब, हम Ks को स्विच कर सकते हैं और उन सभी के लिए WCSS की गणना कर सकते हैं। इस तरह, हम एक अंतर्दृष्टि प्राप्त कर सकते हैं कि क्या K हमें अपनी क्लस्टरिंग को सर्वश्रेष्ठ प्रदर्शन करने के लिए चुनना चाहिए।

गिना जा रहा है डब्ल्यूसीएसएस का प्रयोग Scikit-जानें

सौभाग्य से, हमें प्रत्येक के लिए WCSS की मैन्युअल रूप से गणना करने की आवश्यकता नहीं है K. दिए गए क्लस्टरों की संख्या के लिए K-मीन्स क्लस्टरिंग करने के बाद, हम इसका उपयोग करके WCSS प्राप्त कर सकते हैं inertia_ विशेषता। अब, हम अपने K-मीन्स . पर वापस जा सकते हैं for लूप, क्लस्टर की संख्या को स्वाइप करने के लिए इसका उपयोग करें, और संबंधित WCSS मानों को सूचीबद्ध करें:

wcss = [] 
for number_of_clusters in range(1, 11): 
    kmeans = KMeans(n_clusters = number_of_clusters, random_state = 42)
    kmeans.fit(points) 
    wcss.append(kmeans.inertia_)
wcss

ध्यान दें कि सूची में दूसरा मान ठीक वैसा ही है जैसा हमने पहले के लिए परिकलित किया है K = 2:

[18272.9, # For k=1 
 2964.3999999999996, # For k=2
 1198.75, # For k=3
 861.75,
 570.5,
 337.5,
 175.83333333333334,
 79.5,
 17.0,
 0.0]

उन परिणामों की कल्पना करने के लिए, आइए हम अपना प्लॉट करें Ks डब्ल्यूसीएसएस मूल्यों के साथ:

ks = [1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10]
plt.plot(ks, wcss)

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

एक प्लॉट में रुकावट आती है जब x = 2, लाइन में एक निम्न बिंदु, और इससे भी नीचे वाला बिंदु जब x = 3. ध्यान दें कि यह हमें याद दिलाता है कोहनी का आकार. डब्ल्यूसीएसएस के साथ केएस को प्लॉट करके, हम उपयोग कर रहे हैं कोहनी विधि Ks की संख्या चुनने के लिए। और यह चुना गया K बिल्कुल सबसे निचला कोहनी बिंदु है, तो, यह होगा 3 के बजाय 2, हमारे मामले में:

ks = [1, 2, 3, 4, 5 , 6 , 7 , 8, 9, 10]
plt.plot(ks, wcss);
plt.axvline(3, linestyle='--', color='r')

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

हम K-मीन्स क्लस्टर एल्गोरिथ्म को फिर से चला सकते हैं, यह देखने के लिए कि हमारा डेटा कैसा दिखेगा तीन क्लस्टर:

kmeans = KMeans(n_clusters=3, random_state=42)
kmeans.fit(points)
sns.scatterplot(x = points[:,0], y = points[:,1], hue=kmeans.labels_)

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

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

वैकल्पिक क्लस्टर गुणवत्ता उपाय

ऐसे अन्य उपाय भी हैं जिनका उपयोग क्लस्टर गुणवत्ता का मूल्यांकन करते समय किया जा सकता है:

  • सिल्हूट स्कोर - न केवल इंट्रा-क्लस्टर बिंदुओं के बीच की दूरी का विश्लेषण करता है, बल्कि स्वयं समूहों के बीच की दूरी का भी विश्लेषण करता है
  • समूहों के बीच वर्गों का योग (बीसीएसएस) - WCSS के लिए मीट्रिक पूरक
  • वर्ग त्रुटि का योग (एसएसई)
  • अधिकतम त्रिज्या - एक बिंदु से उसके केन्द्रक तक की सबसे बड़ी दूरी को मापता है
  • औसत त्रिज्या - एक बिंदु से उसके केन्द्रक तक की सबसे बड़ी दूरी का योग समूहों की संख्या से विभाजित होता है।

प्रयोग करने और उनमें से प्रत्येक को जानने की अनुशंसा की जाती है क्योंकि समस्या के आधार पर, कुछ विकल्प सबसे व्यापक रूप से उपयोग किए जाने वाले मीट्रिक की तुलना में अधिक लागू हो सकते हैं (WCSS और सिल्हूट स्कोर).

अंत में, कई डेटा विज्ञान एल्गोरिदम के साथ, हम प्रत्येक क्लस्टर के अंदर भिन्नता को कम करना चाहते हैं और विभिन्न समूहों के बीच भिन्नता को अधिकतम करना चाहते हैं। इसलिए हमारे पास अधिक परिभाषित और वियोज्य क्लस्टर हैं।

दूसरे डेटासेट पर के-मीन्स लागू करना

हमने जो सीखा है उसका उपयोग दूसरे डेटासेट पर करते हैं। इस बार, हम समान वाइन के समूहों को खोजने का प्रयास करेंगे।

नोट: आप डेटासेट डाउनलोड कर सकते हैं यहाँ उत्पन्न करें.

हम आयात करके शुरू करते हैं pandas पढ़ने के लिए wine-clustering CSV (अल्पविराम से अलग किये गए मान) एक में फ़ाइल Dataframe संरचना:

import pandas as pd

df = pd.read_csv('wine-clustering.csv')

इसे लोड करने के बाद, आइए डेटा के पहले पांच रिकॉर्ड पर एक नज़र डालते हैं head() तरीका:

df.head()

इसका परिणाम यह होगा:

	Alcohol 	Malic_Acid 	Ash 	Ash_Alcanity 	Magnesium 	Total_Phenols 	Flavanoids 	Nonflavanoid_Phenols 	Proanthocyanins 	Color_Intensity 	Hue 	OD280 	Proline
0 	14.23 		1.71 		2.43 	15.6 			127 		2.80 			3.06 		0.28 					2.29 				5.64 				1.04 	3.92 	1065
1 	13.20 		1.78 		2.14 	11.2 			100 		2.65 			2.76 		0.26 					1.28 				4.38 				1.05 	3.40 	1050
2 	13.16 		2.36 		2.67 	18.6 			101 		2.80 			3.24 		0.30 					2.81 				5.68 				1.03 	3.17 	1185
3 	14.37 		1.95 		2.50 	16.8 			113 		3.85 			3.49 		0.24 					2.18 				7.80 				0.86 	3.45 	1480
4 	13.24 		2.59 		2.87 	21.0 			118 		2.80 			2.69 		0.39 					1.82 				4.32 				1.04 	2.93 	735

हमारे पास वाइन में मौजूद पदार्थों के कई माप हैं। यहां, हमें श्रेणीबद्ध स्तंभों को बदलने की भी आवश्यकता नहीं होगी क्योंकि वे सभी संख्यात्मक हैं। अब, आइए वर्णनात्मक आँकड़ों पर एक नज़र डालते हैं describe() तरीका:

df.describe().T 

वर्णन तालिका:

 						count 	mean 		std 		min 	25% 	50% 	75% 		max
Alcohol 				178.0 	13.000618 	0.811827 	11.03 	12.3625 13.050 	13.6775 	14.83
Malic_Acid 				178.0 	2.336348 	1.117146 	0.74 	1.6025 	1.865 	3.0825 		5.80
Ash 					178.0 	2.366517 	0.274344 	1.36 	2.2100 	2.360 	2.5575 		3.23
Ash_Alcanity 			178.0 	19.494944 	3.339564 	10.60 	17.2000 19.500 	21.5000 	30.00
Magnesium 				178.0 	99.741573 	14.282484 	70.00 	88.0000 98.000 	107.0000 	162.00
Total_Phenols 			178.0 	2.295112 	0.625851 	0.98 	1.7425 	2.355 	2.8000 		3.88
Flavanoids 				178.0 	2.029270 	0.998859 	0.34 	1.2050 	2.135 	2.8750 		5.08
Nonflavanoid_Phenols 	178.0 	0.361854 	0.124453 	0.13 	0.2700 	0.340 	0.4375 		0.66
Proanthocyanins 		178.0 	1.590899 	0.572359 	0.41 	1.2500 	1.555 	1.9500 		3.58
Color_Intensity 		178.0 	5.058090 	2.318286 	1.28 	3.2200 	4.690 	6.2000 		13.00
Hue 					178.0 	0.957449 	0.228572 	0.48 	0.7825 	0.965 	1.1200 		1.71
OD280 					178.0 	2.611685 	0.709990 	1.27 	1.9375 	2.780 	3.1700 		4.00
Proline 				178.0 	746.893258 	314.907474 	278.00 	500.500 673.500 985.0000 	1680.00

तालिका को देखने से यह स्पष्ट होता है कि कुछ है डेटा में परिवर्तनशीलता - कुछ कॉलम जैसे के लिए Alchool और भी बहुत कुछ है, और दूसरों के लिए, जैसे Malic_Acid, कम। अब हम जांच सकते हैं कि क्या कोई है nullया, NaN हमारे डेटासेट में मान:

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 178 entries, 0 to 177
Data columns (total 13 columns):
 #   Column                Non-Null Count  Dtype  
---  ------                --------------  -----  
 0   Alcohol               178 non-null    float64
 1   Malic_Acid            178 non-null    float64
 2   Ash                   178 non-null    float64
 3   Ash_Alcanity          178 non-null    float64
 4   Magnesium             178 non-null    int64  
 5   Total_Phenols         178 non-null    float64
 6   Flavanoids            178 non-null    float64
 7   Nonflavanoid_Phenols  178 non-null    float64
 8   Proanthocyanins       178 non-null    float64
 9   Color_Intensity       178 non-null    float64
 10  Hue                   178 non-null    float64
 11  OD280                 178 non-null    float64
 12  Proline               178 non-null    int64  
dtypes: float64(11), int64(2)
memory usage: 18.2 KB

डेटा को छोड़ने या इनपुट करने की कोई आवश्यकता नहीं है, क्योंकि डेटासेट में खाली मान नहीं हैं। हम एक सीबोर्न का उपयोग कर सकते हैं pairplot() डेटा वितरण देखने के लिए और यह जांचने के लिए कि क्या डेटासेट कॉलम के जोड़े बनाता है जो क्लस्टरिंग के लिए दिलचस्प हो सकता है:

sns.pairplot(df)

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

पेयरप्लॉट को देखकर, दो कॉलम क्लस्टरिंग उद्देश्यों के लिए आशाजनक प्रतीत होते हैं - Alcohol और OD280 (जो वाइन में प्रोटीन की मात्रा निर्धारित करने की एक विधि है)। ऐसा लगता है कि उनमें से दो को मिलाने वाले भूखंडों पर 3 अलग-अलग समूह हैं।

ऐसे अन्य स्तंभ हैं जो सहसंबंध में भी प्रतीत होते हैं। सबसे एहम Alcohol और Total_Phenols, तथा Alcohol और Flavanoids. उनके पास महान रैखिक संबंध हैं जिन्हें युग्मकथा में देखा जा सकता है।

चूंकि हमारा ध्यान K-मीन्स के साथ क्लस्टरिंग कर रहा है, आइए एक जोड़ी कॉलम चुनें, मान लीजिए Alcohol और OD280, और इस डेटासेट के लिए एल्बो विधि का परीक्षण करें।

नोट: डेटासेट के अधिक कॉलम का उपयोग करते समय, या तो 3 आयामों में प्लॉटिंग करने या डेटा को कम करने की आवश्यकता होगी प्रमुख घटक (पीसीए का उपयोग). यह एक वैध, और अधिक सामान्य दृष्टिकोण है, बस यह सुनिश्चित करें कि वे कितना समझाते हैं और ध्यान रखें कि डेटा आयामों को कम करते समय, कुछ जानकारी हानि होती है - इसलिए साजिश एक है सन्निकटन वास्तविक डेटा का, न कि यह वास्तव में कैसा है।

आइए स्कैटरप्लॉट को उन दो स्तंभों के साथ प्लॉट करें जिन्हें हम समूहों में विभाजित करना चाहते हैं, उन बिंदुओं पर करीब से नज़र डालने के लिए इसकी धुरी होना चाहिए:

sns.scatterplot(data=df, x='OD280', y='Alcohol')

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

अब हम अपने स्तंभों को परिभाषित कर सकते हैं और समूहों की संख्या निर्धारित करने के लिए कोहनी विधि का उपयोग कर सकते हैं। हम इसके साथ एल्गोरिथम भी आरंभ करेंगे kmeans++ बस यह सुनिश्चित करने के लिए कि यह अधिक तेज़ी से अभिसरण करता है:

values = df[['OD280', 'Alcohol']]

wcss_wine = [] 
for i in range(1, 11): 
    kmeans = KMeans(n_clusters = i, init = 'k-means++', random_state = 42)
    kmeans.fit(values) 
    wcss_wine.append(kmeans.inertia_)

हमने WCSS की गणना की है, इसलिए हम परिणामों को प्लॉट कर सकते हैं:

clusters_wine = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
plt.plot(clusters_wine, wcss_wine)
plt.axvline(3, linestyle='--', color='r')

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

एल्बो विधि के अनुसार हमारे यहाँ 3 कलस्टर होने चाहिए। अंतिम चरण के लिए, आइए अपने बिंदुओं को 3 समूहों में क्लस्टर करें और रंगों द्वारा पहचाने गए उन समूहों को प्लॉट करें:

kmeans_wine = KMeans(n_clusters=3, random_state=42)
kmeans_wine.fit(values)
sns.scatterplot(x = values['OD280'], y = values['Alcohol'], hue=kmeans_wine.labels_)

स्किकिट-लर्न प्लेटोब्लॉकचैन डेटा इंटेलिजेंस के साथ के-मीन्स क्लस्टरिंग के लिए निश्चित गाइड। लंबवत खोज। ऐ.

हम क्लस्टर देख सकते हैं 0, 1, तथा 2 ग्राफ में। हमारे विश्लेषण के आधार पर, समूह 0 उच्च प्रोटीन सामग्री और कम अल्कोहल वाली वाइन है, समूह 1 उच्च अल्कोहल सामग्री और कम प्रोटीन वाली वाइन है, और समूह 2 इसकी वाइन में उच्च प्रोटीन और उच्च अल्कोहल दोनों होते हैं।

यह एक बहुत ही रोचक डेटासेट है और मैं आपको सामान्यीकरण और पीसीए के बाद डेटा को क्लस्टर करके विश्लेषण में आगे बढ़ने के लिए प्रोत्साहित करता हूं - परिणामों की व्याख्या करके और नए कनेक्शन ढूंढकर।

निष्कर्ष

कश्मीर साधन क्लस्टरिंग डेटा क्लस्टरिंग के लिए एक सरल लेकिन बहुत प्रभावी गैर-पर्यवेक्षित मशीन लर्निंग एल्गोरिदम है। यह डेटा बिंदुओं के बीच यूक्लिडियन दूरी के आधार पर डेटा को क्लस्टर करता है। K-मीन्स क्लस्टरिंग एल्गोरिथम में टेक्स्ट दस्तावेज़, चित्र, वीडियो और बहुत कुछ समूहबद्ध करने के लिए कई उपयोग हैं।

समय टिकट:

से अधिक स्टैकब्यूज