{
  "fetched_at": "2026-10-25T02:31:01Z",
  "source_url": "https://www.kaggle.com/competitions/data-science-bowl-2017/data",
  "pages": [
    {
      "name": "data-description",
      "content": "<p>NOTE: due to data set usage restrictions, the data for this competition is no longer available for download. </p>\n<p>In this dataset, you are given over a thousand low-dose CT images from high-risk patients in <a href=\"https://en.wikipedia.org/wiki/DICOM\">DICOM</a> format. Each image contains a series with multiple axial slices of the chest cavity. Each image has a variable number of 2D slices, which can vary based on the machine taking the scan and patient.</p>\n<p>The DICOM files have a header that contains the necessary information about the patient id, as well as scan parameters such as the slice thickness.</p>\n<p><img width=\"512\" height=\"512\" alt=\"\" src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/Sample%20MRI%20Slice.png\" style=\"display: block; margin-left: auto; margin-right: auto;\" /></p>\n<p>The competition task is to create an automated method capable of determining whether or not the patient will be diagnosed with lung cancer within one year of the date the scan was taken. The ground truth labels were confirmed by pathology diagnosis.</p>\n<p>The images in this dataset come from many sources and will vary in quality. For example, older scans were imaged with less sophisticated equipment. You should expect the stage 2 data to be, on the whole, more recent and higher quality than the stage 1 data (generally having thinner slice thickness). Ideally, your algorithm should perform well across a range of image quality.</p>\n<h2>Notes</h2>\n<ul>\n<li>Use of external data is permitted in this competition, provided the data is freely available. If you are using a source of external data, you must post the source to the official external data forum thread no later than one week prior to the deadline of the first stage.</li>\n<li>This is a two-stage competition. In order to appear on the final competition leaderboard and receive ranking points, your team must make a submission during both stages of the competition.</li>\n<li>Due to the large file size, <strong>Kaggle is beta testing use of BitTorrent as an alternate means of download</strong>. The image archives are encrypted in order to prevent outside access. Please do not share the decryption password. The large stage1.7z archive hosted on BitTorrent is the same as the version available for direct download.</li>\n</ul>\n<h2>File Descriptions</h2>\n<p>Each patient id has an associated directory of DICOM files. The patient id is found in the DICOM header and is identical to the patient name. The exact number of images will differ from case to case, varying according in the number of slices. Images were compressed as .7z files due to the large size of the dataset.</p>\n<ul>\n<li><strong>stage1.7z</strong> - contains all images for the first stage of the competition, including both the training and test set. This is file is also hosted on BitTorrent.</li>\n<li><strong>stage1_labels.csv</strong> - contains the cancer ground truth for the stage 1 training set images</li>\n<li><strong>stage1_sample_submission.csv</strong> - shows the submission format for stage 1. You should also use this file to determine which patients belong to the leaderboard set of stage 1.</li>\n<li><strong>sample_images.7z</strong> - a smaller subset set of the full dataset, provided for people who wish to preview the images before downloading the large file.</li>\n<li><strong>data_password.txt</strong> - contains the decryption key for the image files</li>\n</ul>\n<p>The DICOM standard is complex and there are a number of different tools to work with DICOM files. You may find the following resources helpful for managing the competition data:</p>\n<ul>\n<li>The <a href=\"http://www.osirix-viewer.com/\">lite version of OsiriX</a> is useful for viewing images on OSX.</li>\n<li><a href=\"https://pydicom.readthedocs.org/en/latest/\">pydicom</a>: A package for working with images in python.</li>\n<li><a href=\"https://cran.r-project.org/web/packages/oro.dicom/index.html\">oro.dicom</a>: A package for working with images in R.</li>\n<li><a href=\"http://www.idoimaging.com/program/352\">Mango</a>: A useful DICOM viewer for Windows users.</li>\n</ul>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "Description",
      "content": "<p>In the United States, lung cancer strikes 225,000 people every year, and accounts for $12 billion in health care costs. Early detection is critical to give patients the best chance at recovery and survival.</p>\n<p>One year ago, the office of the U.S. Vice President spearheaded a bold new initiative, the Cancer Moonshot, to make a decade's worth of progress in cancer prevention, diagnosis, and treatment in just 5 years.</p>\n<p>In 2017, the Data Science Bowl will be a critical milestone in support of the Cancer Moonshot by convening the data science and medical communities to develop lung cancer detection algorithms.</p>\n<p>Using a data set of thousands of high-resolution lung scans provided by the National Cancer Institute, participants will develop algorithms that accurately determine when lesions in the lungs are cancerous. This will dramatically reduce the false positive rate that plagues the current detection technology, get patients earlier access to life-saving interventions, and give radiologists more time to spend with their patients.</p>\n<p>This year, the Data Science Bowl will award $1 million in prizes to those who observe the right patterns, ask the right questions, and in turn, create unprecedented impact around cancer screening care and prevention. The funds for the prize purse will be provided by the Laura and John Arnold Foundation.</p>\n<p>Visit DataScienceBowl.com to: <br />• Sign up to <a href=\"http://www.datasciencebowl.com/contact/\">receive news</a> about the competition<br />• Learn about the <a href=\"http://www.datasciencebowl.com/competitions/\">history of the Data Science Bowl</a> and past competitions<br />• Read our <a href=\"http://www.datasciencebowl.com/data-science-insights/\">latest insights</a> on emerging analytics techniques</p>\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/illustration-lung-3.5.jpg\" alt=\"BAH Lung\" width=\"576\" height=\"716\" style=\"display: block; margin-left: auto; margin-right: auto;\" /></p>\n<h3>Acknowledgments</h3>\n<p>The Data Science Bowl is presented by</p>\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3978/media/booz_kaggle.png\" alt=\"BAH and Kaggle\" width=\"537\" height=\"89\" style=\"display: block; margin-left: auto; margin-right: auto;\" /></p>\n<h4>Competition Sponsors</h4>\n<p>Laura and John Arnold Foundation<br />Cancer Imaging Program of the National Cancer Institute<br />American College of Radiology<br />Amazon Web Services<br />NVIDIA</p>\n<h4>Data Support Providers</h4>\n<p>National Lung Screening Trial<br />The Cancer Imaging Archive<br />Diagnostic Image Analysis Group, Radboud University<br />Lahey Hospital &amp; Medical Center<br />Copenhagen University Hospital</p>\n<h4>Supporting Organizations </h4>\n<p>Bayes Impact<br />Black Data Processng Associates<br />Code the Change<br />Data Community DC<br />DataKind<br />Galvanize<br />Great Minds in STEM<br />Hortonworks<br />INFORMS<br />Lesbians Who Tech<br />NSBE<br />Society of Asian Scientists &amp; Engineers<br />Society of Women Engineers<br />University of Texas Austin, Business Analytics Program,<br />McCombs School of Business<br />US Dept. of Health and Human Services<br />US Food and Drug Administration<br />Women in Technology<br />Women of Cyberjutsu</p>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "Evaluation",
      "content": "<p>Submissions are scored on the log loss:</p>\r\n<p>$$<br />\\textrm{LogLoss} = - \\frac{1}{n} \\sum_{i=1}^n \\left[ y_i \\log(\\hat{y}_i) + (1 - y_i) \\log(1 - \\hat{y}_i)\\right],<br />$$</p>\r\n<p>where</p>\r\n<ul>\r\n<li>n is the number of patients in the test set</li>\r\n<li>\\\\( \\hat{y}_i \\\\) is the predicted probability of the image belonging to a patient with cancer</li>\r\n<li>\\\\( y_i \\\\) is 1 if the diagnosis is cancer, 0 otherwise</li>\r\n<li>\\\\( log() \\\\) is the natural (base e) logarithm</li>\r\n</ul>\r\n<p>Note: the actual submitted predicted probabilities are replaced with \\\\(max(min(p,1-10^{-15}),10^{-15})\\\\). A smaller log loss is better.</p>\r\n<h2>Submission File</h2>\r\n<p>For each patient id in the test set, you must submit a probability. The file should have a header and be in the following format:</p>\r\n<pre>id,cancer<br />01e349d34c02410e1da273add27be25c,0.5<br />05a20caf6ab6df4643644c923f06a5eb,0.5<br />0d12f1c627df49eb223771c28548350e,0.5<br />...</pre>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "Prizes",
      "content": "<ul>\r\n<li>1st place - $500,000</li>\r\n<li>2nd place - $200,000</li>\r\n<li>3rd place - $100,000</li>\r\n<li>4th place - $25,000</li>\r\n<li>5th place - $25,000</li>\r\n<li>6th place - $25,000</li>\r\n<li>7th place - $25,000</li>\r\n<li>8th place - $25,000</li>\r\n<li>9th place - $25,000</li>\r\n<li>10th place - $25,000</li>\r\n<li>$5,000 each to the top three most highly voted Kernels (Total of $15,000)</li>\r\n<li>$10,000 in prizes to be awarded for sharing your DSB journey on social media – more details to be announced on February 1, 2017</li>\r\n</ul>\r\n<p>In addition to the $1 million in cash prizes awarded by the Arnold Foundation to the winners of this competition, NVIDIA and Amazon have made the following prizes available. </p>\r\n<ul>\r\n<li>NVIDIA will provide free passes to the <a href=\"http://www.gputechconf.com/\">GPU Technology Conference</a> (GTC) for all members of the top three winning teams (first, second, and third place).</li>\r\n<li>NVIDIA’s <a href=\"https://www.nvidia.com/en-us/deep-learning-ai/education/\">Deep Learning Institute</a> (DLI) will provide the first one thousand (1,000) DSB competitors with one hundred and twenty (120) credits each to access the DLI.</li>\r\n<li>Amazon will provide, at an unspecified time during this competition, access to $500 in AWS credits to each of the first 100 participants to sign up. </li>\r\n</ul>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "rules",
      "content": "<!-- Begin Base Rules -->\n<h3>One account per participant</h3>\n<p>You cannot sign up to Kaggle from multiple accounts and therefore you cannot submit from multiple accounts.</p>\n<h3>No private sharing outside teams</h3>\n<p>Privately sharing code or data outside of teams is not permitted. It's okay to share code if made available to all participants on the forums.</p>\n<h3>Team Mergers</h3>\n<p>Team mergers are allowed and can be performed by the team leader. In order to merge, the combined team must have a total submission count less than or equal to the maximum allowed as of the merge date. The maximum allowed is the number of submissions per day multiplied by the number of days the competition has been running.</p>\n<h3>Team Limits</h3>\n<p>There is no maximum team size.</p>\n<h3>Submission Limits</h3>\n<p>You may submit a maximum of 3 entries per day.</p>\n<p>You may select up to 2 final submissions for judging.</p>\n<h3>Competition Timeline</h3>\n<p>Start Date: <strong>1/12/2017 2:00 PM UTC</strong></p>\n<p>Merger Deadline: <strong>3/31/2017 11:59 PM UTC</strong></p>\n<p>Entry Deadline: <strong>3/31/2017 11:59 PM UTC</strong></p>\n<p>End Date: <strong>4/12/2017 11:59 PM UTC</strong></p>\n<!-- End Base Rules -->\n<ul>\n<li>This is a two-stage competition. In order to appear on the final competition leaderboard and receive ranking points, your team must make a submission during both stages of the competition.</li>\n<li>Use of external data is permitted, provided the data is freely available. If you are using a source of external data, you must post the source to the official external data forum thread no later than one week prior to the deadline of the first stage.</li>\n</ul>\n<h3>COMPETITION-SPECIFIC TERMS</h3>\n<p>COMPETITION NAME (the 'Competition'): Data Science Bowl 2017</p>\n<p>COMPETITION SPONSOR: Booz Allen Hamilton</p>\n<p>COMPETITION WEBSITE: https://www.kaggle.com/c/data-science-bowl-2017</p>\n<p>PRIZES: $1,000,000 total prizes</p>\n<p>WINNER LICENSE TYPE: Open Source License</p>\n<p>MAXIMUM TEAM SIZE: as listed above</p>\n<p>MAXIMUM SUBMISSIONS PER DAY: as listed above</p>\n<h3>ELIGIBILITY NOTE</h3>\n<p>Members of the following organizations are invited to participate in the competition, however they will not be eligible to win a cash prize:</p>\n<ul>\n<li>Booz Allen Hamilton</li>\n<li>NCI Division of Cancer Treatment and Diagnosis</li>\n<li>NCI Division of Cancer Prevention</li>\n<li>Functional Image Analysis group, Radboud University</li>\n<li>The Cancer Imaging Archive</li>\n<li>Lahey Hospital & Medical Center</li>\n<li>Copenhagen University Hospital</li>\n</ul>\n<p>Additionally, any individual determined to have access to the test data prior to the Competition will not be eligible for a cash prize. </p>\n<h3>COMPETITION FRAMEWORK</h3>\n<p>These are the complete, official rules for the Competition (the 'Competition Rules') and incorporate by reference the contents of the Competition Website listed above.</p>\n<p>By downloading a dataset linked from the Competition Website, submitting an entry to this Competition, or joining a Team in this Competition, you are agreeing to be bound by these Competition Rules which constitute a binding agreement between you and the Competition Sponsor.</p>\n<p>The Competition is sponsored by the Competition Sponsor listed above and hosted on the Sponsor's behalf by Kaggle Inc ('Kaggle').</p>\n<p>The Competition will run from Start Date to End Date as listed on the Competition Website. Note that Competition deadlines are subject to change and additional hurdle deadlines may be introduced during the Competition. Any additional or altered deadlines not already described in these Competition Rules will be publicized to the Participants via the Competition Website. It is the Participant's responsibility in this Competition to check the website regularly throughout the Competition to stay informed of any new or updated deadlines. Neither Kaggle nor Competition Sponsor are responsible for any Participant's failure to do so.</p>\n<p>Each registered individual or Team is referred to as a Participant. You may only participate using a single, unique Kaggle account registered at http://www.kaggle.com. Participating using more than one Kaggle account per individual Participant is a breach of these Competition Rules and Competition Sponsor reserves the right to disqualify any Participant (or Team including Participant) who is found to breach these Competition Rules.</p>\n<h3>ELIGIBILITY</h3>\n<p>The Competition is open to all individuals over the age of 18 at the time of entry and to all validly formed legal entities that have not declared or been declared in bankruptcy.</p>\n<p>Officers, directors, employees and advisory board members (and their immediate families and members of the same household) of the Competition Sponsor, Kaggle and their respective affiliates, subsidiaries, contractors (with the express exception of Kaggle's authorized Kaggle Community Evangelists), agents, judges and advertising and promotion agencies are not eligible to receive any Prize in the Competition.</p>\n<p>You are not eligible to receive any Prize in the Competition if you are a resident of a country designated by the United States Treasury’s Office of Foreign Assets Control (see &lt;http://www.treasury.gov/resource-center/sanctions/SDN-List/Pages/default.aspx&gt; for additional information).</p>\n<h3>SUBMISSIONS</h3>\n<p>'Submission' means the material submitted by you in the manner and format specified on the Website via the Submission form on the Website. You (or if you are part of a Team, your Team) may submit up to the maximum number of Submissions per day as specified above. All Submissions must be uploaded to the Website in the manner and format specified on the Website. Submissions must be received prior to the Competition deadline and adhere to the guidelines for Submissions specified on the Website.</p>\n<p>Submissions may not use or incorporate information from hand labeling or human prediction of the validation dataset or test data records.</p>\n<p>If the Competition is a multi-stage Competition with temporally separate training data and/or leaderboard data, one or more valid Submissions must be made and selected during each stage of the Competition in the manner described on the Competition Website.</p>\n<h3>INTELLECTUAL PROPERTY</h3>\n<h4>DATA</h4>\n<p>'Data' means the Data or Datasets linked from the Competition Website for the purpose of use by Participants in the Competition. For the avoidance of doubt, Data is deemed for the purpose of these Competition Rules to include any prototype or executable code provided to Participants by Kaggle or Competition Sponsor via the Website. Participants must use the Data only as permitted by these Competition Rules and any associated data use rules specified on the Competition Website.</p>\n<p>Unless otherwise permitted by the terms of the Competition Website, Participants must use the Data solely for the purpose and duration of the Competition, including but not limited to reading and learning from the Data, analyzing the Data, modifying the Data and generally preparing your Submission and any underlying models and participating in forum discussions on the Website. Participants agree to use suitable measures to prevent persons who have not formally agreed to these Competition Rules from gaining access to the Data and agree not to transmit, duplicate, publish, redistribute or otherwise provide or make available the Data to any party not participating in the Competition. Participants agree to notify Kaggle immediately upon learning of any possible unauthorized transmission or unauthorized access of the Data and agree to work with Kaggle to rectify any unauthorized transmission. Participants agree that participation in the Competition shall not be construed as having or being granted a license (expressly, by implication, estoppel, or otherwise) under, or any right of ownership in, any of the Data.</p>\n<h4>EXTERNAL DATA</h4>\n<p>Unless otherwise expressly stated on the Competition Website, Participants must not use data other than the Data to develop and test their models and Submissions. Competition Sponsor reserves the right in its sole discretion to disqualify any Participant who Competition Sponsor discovers has undertaken or attempted to undertake the use of data other than the Data, or who uses the Data other than as permitted according to the Competition Website and in these Competition Rules, in the course of the Competition.</p>\n<h4>CODE SHARING</h4>\n<p>Participants are prohibited from privately sharing source or executable code developed in connection with or based upon the Data, and any such sharing is a breach of these Competition Rules and may result in disqualification.</p>\n<p>Participants are permitted to publicly share source or executable code developed in connection with or based upon the Data, or otherwise relevant to the Competition, provided that such sharing does not violate the intellectual property rights of any third party. By so sharing, the sharing Participant is thereby deemed to have licensed the shared code under the MIT License (an open source software license commonly described at &lt;http://opensource.org/licenses/MIT&gt;).</p>\n<h4>OPEN-SOURCE CODE</h4>\n<p>A Submission will be ineligible to win a prize if it was developed using code containing or depending on software licensed under an open source license:</p>\n<p>* <em>other than</em> an Open Source Initiative-approved license (see &lt;http://opensource.org/&gt;); or<br />* an open source license that prohibits commercial use.</p>\n<h3>WINNING</h3>\n<h4>DETERMINING WINNERS</h4>\n<p>This Competition is a challenge of skill and the final results are determined solely by leaderboard ranking on the private leaderboard (subject to compliance with these Competition Rules). Participants' scores and ranks on the Competition Website at any given stage of the Competition will be based on the evaluation metric described on the Competition Website, as determined by applying the predictions in the Submission to the ground truth of a validation dataset whose instances were a fixed set sampled from the Data.</p>\n<p>The evaluation metric used for scoring and ranking Submissions will be displayed on the Competition Website.</p>\n<p>Prize awards are subject to verification of eligibility and compliance with these Competition Rules. All decisions of the Competition Sponsor and judges will be final and binding on all matters relating to this Competition. Competition Sponsor reserves the right to examine the Submission and any associated code or documentation for compliance with these Competition Rules. In the event that the Submission demonstrates a breach of these Competition Rules, Competition Sponsor may at its discretion take either of the following actions:</p>\n<p>* disqualify your Submission(s); or <br />* require that you remediate within one week all issues identified in your Submission(s) (including, without limitation, the resolution of license conflicts, the fulfillment of all obligations required by software licenses, and the removal of any software that violates the software restrictions).</p>\n<h4>RESOLVING TIES</h4>\n<p>A tie between two or more valid and identically ranked submissions will be resolved in favour of the tied submission that was submitted first.</p>\n<h4>DECLINING PRIZES</h4>\n<p>A Participant may decline to be nominated as a Winner by notifying Kaggle directly within one week following the Competition deadline, in which case the declining Participant forgoes any prize or other features associated with winning the Competition. Kaggle reserves the right to disqualify a Participant who so declines at Kaggle's sole discretion if Kaggle deems disqualification appropriate.</p>\n<h3>WINNERS' OBLIGATIONS</h3>\n<h4>DELIVERY &amp; DOCUMENTATION</h4>\n<p>As a condition of receipt of the Prize, the Prize winner must deliver the final model’s software code as used to generate the winning Submission and associated documentation (consistent with the winning model documentation template available on the kaggle wiki at https://www.kaggle.com/wiki/WinningModelDocumentationTemplate) to the Competition Sponsor. The delivered software code must be capable of generating the winning Submission and contain a description of resources required to build and/or run the executable code successfully.</p>\n<p>If a potential winning Participant or Team member is a U.S. citizen, potential winner must also sign and return an IRS W-9 form, or if a foreign resident, an IRS W-8BEN form, within the stated time in order to claim the prize.</p>\n<p>Potential winners will be disqualified and the prize may be awarded to an alternate winner (the next-ranked qualified Participant on the leaderboard) if</p>\n<p>* the required documentation is not returned within 14 days after receipt of any request to provide documentation;<br />* prize notification letter/email or prize is returned as undeliverable; or<br />* potential winner or winning Team member is disqualified for any reason.</p>\n<p>By accepting any Prize, each Participant receiving a Prize thereby agrees to use of his/her name, address, likeness and/or Prize information by Kaggle and Competition Sponsor for promotional purposes in any medium without additional compensation.</p>\n<h4>PARTICIPANT INTELLECTUAL PROPERTY LICENSING</h4>\n<p>As a further condition of receipt of a Prize, each winning Participant thereby licenses their winning Submission and the source code used to generate the Submission according to the Winner License Type specified above (note: if no Winner License Type is specified above, the Winner License Type is deemed to be Non-Exclusive License).</p>\n<h5>PUBLIC COMPETITIONS: NON-EXCLUSIVE LICENSE</h5>\n<p>If the Winner License Type for the Competition (see Winner License Type above) is a Non-Exclusive License then each Winner by accepting a Prize thereby:</p>\n<p>* grants to Competition Sponsor and its designees a worldwide, non-exclusive, sub-licensable, transferable, fully paid-up, royalty-free, perpetual, irrevocable right to use, not use, reproduce, distribute, create derivative works of, publicly perform, publicly display, digitally perform, make, have made, sell, offer for sale and import their winning Submission and the source code used to generate the Submission, in any media now known or hereafter developed, for any purpose whatsoever, commercial or otherwise, without further approval by or payment to Participant; and<br />* represents that he/she/it has the unrestricted right to grant that license.</p>\n<h5>RESEARCH COMPETITIONS: OPEN SOURCE LICENSE</h5>\n<p>If the Winner License Type for the Competition (see Winner License Type above) is Open Source License, then each Winner by accepting a Prize thereby:</p>\n<p>* licenses their winning Submission and the source code used to generate the Submission under the MIT License (an open source software license commonly described at &lt;http://opensource.org/licenses/MIT&gt;), unless another open source license is chosen explicitly from the list of those approved by the Open Source Initiative at &lt;http://opensource.org/licenses/&gt;; and<br />* represents that he/she/it has the unrestricted right to grant that license.</p>\n<h5>RECRUITING COMPETITION SUBMISSION LICENSE GRANT</h5>\n<p>If the Competition is classed above as a Recruiting Competition, Participant agrees to grant and hereby grants to Competition Sponsor a perpetual, irrevocable, worldwide, royalty-free, transferable, and sublicenseable right to use, review, reproduce, and internally distribute the Submission (including any and all submitted source code) in connection with evaluating Participant's suitability for employment, provided that the Submission licensed as set forth above will not be used for Competition Host’s commercial purposes except as may otherwise be set forth in this Agreement.</p>\n<h4>CHEATING</h4>\n<p>Participating using more than one Kaggle account is deemed cheating and, if discovered, will result in disqualification from the Competition and any other affected Competitions and may result in banning or deactivation of affected Kaggle accounts.</p>\n<h4>RECEIVING PRIZES</h4>\n<p>After verification of eligibility, each Prize winner will receive the prize in the form of a check or wire transfer made out to the Prize winner (if an individual, or to the individual Team members if a Team). Allow 30 days from final confirmation for Prize delivery. Any winners who are U.S. citizens will receive an IRS 1099 form in the amount of their prize at the appropriate time. Prize winners are responsible for any taxes, fees or other liability resulting from their receipt of a Prize.</p>\n<h3>TEAMS</h3>\n<h4>FORMING A TEAM</h4>\n<p>Multiple individuals or entities may collaborate as a team (“Team”). You may not participate on more than one Team. Each Team member must be a single individual operating a separate Kaggle account. You must register individually for the Competition before joining a Team. You must confirm your Team membership to make it official by responding to the Team notification message which will be sent to your Account.</p>\n<p>Team membership may not exceed the Maximum Team Size.</p>\n<h4>TEAM MERGERS</h4>\n<p>Teams may be permitted to merge at Kaggle’s discretion, so long as the merged Team meets all requirements in these Competition Rules. Kaggle will review any merger request and will either approve or reject the request within three business days. Merger requests may be rejected if the combined number of Entries made by the merging Teams exceeds the number of Entries permissible at the date of the merger request. Team merger requests will not be permitted within seven days of any deadline listed on the Competition Website.</p>\n<h4>TEAM PRIZES</h4>\n<p>If a Team wins a monetary Prize, Competition Sponsor will allocate the Prize money in even shares between the Team members unless the Team unanimously contacts Kaggle via the Competition Website within three business days following the Submission deadline to request an alternative prize distribution.</p>\n<h3>WARRANTIES AND OBLIGATIONS</h3>\n<h4>PARTICIPANT WARRANTIES AND OBLIGATIONS</h4>\n<p>By registering, you agree that (a) your Account is complete, correct and accurate and (b) your registration may be rejected or terminated and all Entries submitted by you and/or your Team may be disqualified if any of the information in your Account is (or Competition Sponsor has reasonable grounds to believe it is) incomplete, incorrect or inaccurate. You are solely responsible for your Account. All registration information is deemed collected in the United States.</p>\n<p>Participation is subject to all federal, state and local laws and regulations. Void where prohibited or restricted by law. You are responsible for checking applicable laws and regulations in your jurisdiction before participating in the Competition to make sure that your participation is legal. You are responsible for all taxes and reporting related to any award that you may receive as part of the Competition. You are responsible for abiding by your employer's policies regarding participation in the Competition. Competition Sponsor disclaims any and all liability or responsibility for disputes arising between you and your employer related to this Competition.</p>\n<p>Each Participant is solely responsible for all equipment, including but not necessarily limited to a computer and internet connection necessary to access the Website and to develop and upload any Submission, and any telephone, data, hosting or other service fees associated with such access, as well as all costs incurred by or behalf of the Entrant in participating in the Competition.</p>\n<p>By entering a Submission, you represent and warrant that all information you enter on the Website is true and complete to the best of your knowledge, that you have the right and authority to make the Submission (including any underlying code and model) on your own behalf or on behalf of the persons and entities that you specify within the Submission, and that your Submission:</p>\n<p>* is your own original work, or is used by permission, in which case full and proper credit and identify is given and the third party contributions are clearly identified within your Submission;<br />* does not contain confidential information or trade secrets and is not the subject of a registered patent or pending patent application;<br />* does not violate or infringe upon the patent rights, industrial design rights, copyrights, trademarks, rights of privacy, publicity or other intellectual property or other rights of any person or entity;<br />* does not contain malicious code, such as viruses, timebombs, cancelbots, worms, Trojan horses or other potentially harmful programs or other material or information; <br />* does not and will not violate any applicable law, statute, ordinance, rule or regulation;<br />* does not trigger any reporting or royalty obligation to any third party; and<br />* was not previously published and has not won any other prize/award. <br />A breach of any of these warranties will result in the corresponding Submission being invalid.</p>\n<h4>LIMITATION OF LIABILITY</h4>\n<p>By participating in the Competition, each Participant agrees to release, indemnify and hold harmless Competition Sponsor, Kaggle, their respective affiliates, subsidiaries, advertising and promotions agencies, as applicable, and each of their respective agents, representatives, officers, directors, shareholders, and employees from and against any injuries, losses, damages, claims, actions and any liability of any kind resulting from or arising out of your participation in or association with the Competition. Competition Sponsor is not responsible for any miscommunications such as technical failures related to computer, telephone, cable, and unavailable network or server connections, related technical failures, or other failures related to hardware, software or virus, or incomplete, late or misdirected Submissions. Competition Sponsor reserves the right to cancel, modify or suspend the Competition should any computer virus, bug or other technical difficulty or other causes beyond the control of Competition Sponsor corrupt the administration, security or proper play of the Competition, and to determine winners from among Submission not affected by the corruption, if any, in its sole discretion.</p>\n<p>Neither Kaggle nor Competition Sponsor are responsible for (a) late, lost, stolen, damaged, garbled, incomplete, incorrect or misdirected Entries or other communications, (b) errors, omissions, interruptions, deletions, defects, or delays in operations or transmission of information, in each case whether arising by way of technical or other failures or malfunctions of computer hardware, software, communications devices, or transmission lines, or (c) data corruption, theft, destruction, unauthorized access to or alteration of Submission materials, loss or otherwise. Neither Kaggle nor Competition Sponsor are responsible for electronic communications or emails which are undeliverable as a result of any form of active or passive filtering of any kind, or insufficient space in any email account to receive email messages. Competition Sponsor disclaims any liability for damage to any computer system resulting from participation in, or accessing or downloading information in connection with, the Competition.</p>\n<h4>RESERVATION OF RIGHTS</h4>\n<p>Competition Sponsor reserves the right to modify the Start Date, End Date, and the right to modify, add or remove additional Competition deadlines for any reason. Any changes will be communicated through the Competition Website. Competition Sponsor also reserves the right to modify, remove or add Data to the Website upon notice via the Competition Website. NEITHER KAGGLE NOR COMPETITION SPONSOR ARE RESPONSIBLE FOR ANY FAILURE OF A PARTICIPANT TO RECEIVE DATA CHANGES.</p>\n<h3>MISCELLANEOUS</h3>\n<h4>SEVERABILITY</h4>\n<p>The invalidity or unenforceability of any provision of these Competition Rules shall not affect the validity or enforceability of any other provision. In the event that any provision is determined to be invalid or otherwise unenforceable or illegal, these Competition Rules shall otherwise remain in effect and be construed in accordance with their terms as if the invalid or illegal provision was not contained herein.</p>\n<h4>LAW</h4>\n<p>You agree that these terms and the relationship between you and Competition Sponsor shall be governed by the laws of the State of California and the United States of America.</p>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "Timeline",
      "content": "<ul>\r\n<li><strong>March 31, 2017</strong> - Entry deadline. You must accept the competition rules before this date in order to compete.</li>\r\n<li><strong>March 31, 2017 </strong>- Team merger deadline. This is the last day participants may join or merge teams.</li>\r\n<li><strong>April 7, 2017</strong> - Stage one deadline and stage two data release. Your model must be finalized and uploaded to Kaggle by this deadline. After this deadline, the test set is released, the answers to the validation set are released, and participants make predictions on the test set. <em><strong>PLEASE NOTE: If you do not make a submission during the second stage of the competition, you will not appear on the final competition leaderboard and you will not receive competition ranking points. </strong></em></li>\r\n<li><strong>April 12, 2017</strong> - Final submission deadline.</li>\r\n</ul>\r\n<p>All deadlines are at 11:59 PM UTC on the corresponding day unless otherwise noted. The competition organizers reserve the right to update the contest timeline if they deem it necessary.</p>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "About",
      "content": "<p>The Data Science Bowl, presented by Booz Allen and Kaggle, is the world’s premier data science for social good competition. It convenes data scientists, technologists, domain experts, and organizations to take on the world’s challenges with data and technology. It’s a platform through which individuals can harness their passion, unleash their curiosity, and amplify their impact to effect change on a global scale.</p>\r\n<p>During a 90-day period, participants, either alone or working in teams, gain access to unique data sets to develop algorithms that address a specific challenge. And each year, the competition awards hundreds of thousands of dollars in prize money to top teams.</p>\r\n<p>In 2014/2015, participants <a href=\"http://www.datasciencebowl.com/competitions/assessing-ocean-health-at-massive-speed-and-scale/\">examined more than 100,000 underwater images</a>, provided by the Hatfield Marine Science Center, to assess ocean health at a massive speed and scale.</p>\r\n<p>In 2015/2016, they applied <a href=\"http://www.datasciencebowl.com/competitions/transforming-how-we-diagnose-heart-disease/\">analytics in cardiology</a>, transforming the practice of assessing heart function.</p>\r\n<p>In 2017, we’ll turn machine intelligence against lung cancer, and work to end the disease as we know it.</p>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/DSB_Zone_Graphic_kids-01.png\" alt=\"DSB 2017\" width=\"565\" height=\"301\" style=\"display: block; margin-left: auto; margin-right: auto;\" /></p>\r\n<p>Visit <a href=\"http://www.DataScienceBowl.com\">DataScienceBowl.com</a> to learn more about the competition, get insights into emerging analytics techniques, and sign up for news alerts.</p>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "Tutorial",
      "content": "<div>\r\n<h1>U-Net Segmentation Approach to Cancer Diagnosis <a id=\"user-content-u-net-segmentation-approach-to-cancer-diagnosis\" class=\"anchor\" href=\"#u-net-segmentation-approach-to-cancer-diagnosis\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h1>\r\n<p><em>written by Jonathan Mulholland and Aaron Sander, Booz Allen Hamilton</em></p>\r\n<p>In this tutorial, we will show one approach to predicting whether a CT scan is of a patient who either has or will develop cancer within the next 12 months or not.</p>\r\n<p>We will train a network to segment out potentially cancerous nodules and then use the characteristics of that segmentation to make predictions about the diagnosis of the scanned patient within a 12 month time frame.</p>\r\n<p>The code for this tutorial can be found at <a href=\"https://github.com/booz-allen-hamilton/DSB3Tutorial\">https://github.com/booz-allen-hamilton/DSB3Tutorial</a></p>\r\n<h2>Dependencies and tools <a id=\"user-content-dependencies-and-tools\" class=\"anchor\" href=\"#dependencies-and-tools\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\r\n<p>This tutorial uses python and has the following dependencies</p>\r\n<ul>\r\n<li>numpy</li>\r\n<li>scikit-image</li>\r\n<li>scikit-learn</li>\r\n<li>keras (tensorflow backend)</li>\r\n<li>matplotlib</li>\r\n<li>pydicom</li>\r\n<li>SimpleITK</li>\r\n</ul>\r\n<p>Note: Keras allows multiple backends for use when training. We chose a GPU enabled installation of tensorflow as the backend of Keras.</p>\r\n<p>In order to identify regions with nodules, we will use a U-Net style convolutional network which was designed for segmenting neuronal structures. <a href=\"https://arxiv.org/abs/1505.04597\">https://arxiv.org/abs/1505.04597</a></p>\r\n<p>Our code for the network was based on a turorial posted by Marko Jocic on the Kaggle forum for the Ultrasound Nerve Segmentation Challenge. <a href=\"https://www.kaggle.com/c/ultrasound-nerve-segmentation/forums/t/21358/0-57-deep-learning-keras-tutorial\">https://www.kaggle.com/c/ultrasound-nerve-segmentation/forums/t/21358/0-57-deep-learning-keras-tutorial</a></p>\r\n<p>The images we'll be predicting cancer diagnoses on are scans from low-dose helical computed tomography (CT). The appearance on nodules within the CT scan indicate the possibility of cancer, and we will need training examples with marked nodules in order train the U Net to find these nodules. Rather than hand label images, we turn to the Lung Nodule Analysis 2016 (LUNA2016) challenge which has made available CT images with annotated nodule locations. We will first use the LUNA data set to generate an appropriate training set for our U-Net. We will use these examples to train our supervised segmenter.</p>\r\n<h2>Constructing a training set from the LUNA 2016 data <a id=\"user-content-constructing-a-training-set-from-the-luna-2016-data\" class=\"anchor\" href=\"#constructing-a-training-set-from-the-luna-2016-data\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\r\n<p>We are going to use the nodule locations as given in annotations.csv and extract three transverse slices that contain the largest nodule from each patient scan. Masks will be created for those slices based on the nodule dimensions given in annotations.csv. The output of this file will be two files for each patient scan: a set of images and a set of corresponding nodule masks. The data from the LUNA 2016 challenge can be found at <a href=\"https://luna16.grand-challenge.org/\">https://luna16.grand-challenge.org/</a></p>\r\n<p>First we import the necessary tools and find the largest nodule in the patient scan. There are multiple nodule listings for some patients in annotations.csv. We're using a pandas DataFrame named <code>df_node</code> to keep track of the case numbers and the node information. The node information is an (x,y,z) coordinate in mm using a coordinate system defined in the .mhd file.</p>\r\n<p>The following snippets of code are from LUNA_mask_extraction.py:</p>\r\n<pre><code>import SimpleITK as sitk\r\nimport numpy as np\r\nimport csv\r\nfrom glob import glob\r\nimport pandas as pd\r\nfile_list=glob(luna_subset_path+\"*.mhd\")\r\n#####################\r\n#\r\n# Helper function to get rows in data frame associated \r\n# with each file\r\ndef get_filename(case):\r\n    global file_list\r\n    for f in file_list:\r\n        if case in f:\r\n            return(f)\r\n#\r\n# The locations of the nodes\r\ndf_node = pd.read_csv(luna_path+\"annotations.csv\")\r\ndf_node[\"file\"] = df_node[\"seriesuid\"].apply(get_filename)\r\ndf_node = df_node.dropna()\r\n#####\r\n#\r\n# Looping over the image files\r\n#\r\nfcount = 0\r\nfor img_file in file_list:\r\n    print \"Getting mask for image file %s\" % img_file.replace(luna_subset_path,\"\")\r\n    mini_df = df_node[df_node[\"file\"]==img_file] #get all nodules associate with file\r\n    if len(mini_df)&gt;0:       # some files may not have a nodule--skipping those \r\n        biggest_node = np.argsort(mini_df[\"diameter_mm\"].values)[-1]   # just using the biggest node\r\n        node_x = mini_df[\"coordX\"].values[biggest_node]\r\n        node_y = mini_df[\"coordY\"].values[biggest_node]\r\n        node_z = mini_df[\"coordZ\"].values[biggest_node]\r\n        diam = mini_df[\"diameter_mm\"].values[biggest_node]\r\n</code></pre>\r\n<h2>Getting the nodule position in the mhd files <a id=\"user-content-getting-the-nodule-position-in-the-mhd-files\" class=\"anchor\" href=\"#getting-the-nodule-position-in-the-mhd-files\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\r\n<p>The nodule locations are given in terms of millimeters relative to a coordinate system defined by the CT scanner. The image data is given as a varying length stack of 512 X 512 arrays. In order to translate the voxel position to the world coordinate system, one needs to know the real world position of the [0,0,0] voxel and the voxel spacing in mm.</p>\r\n<p>To find the voxel coordinates of a nodule, given its real world position, we use the <code>GetOrigin()</code> and <code>GetSpacing()</code> method of the itk image object:</p>\r\n<pre><code>itk_img = sitk.ReadImage(img_file) \r\nimg_array = sitk.GetArrayFromImage(itk_img) # indexes are z,y,x (notice the ordering)\r\ncenter = np.array([node_x,node_y,node_z])   # nodule center\r\norigin = np.array(itk_img.GetOrigin())      # x,y,z  Origin in world coordinates (mm)\r\nspacing = np.array(itk_img.GetSpacing())    # spacing of voxels in world coor. (mm)\r\nv_center =np.rint((center-origin)/spacing)  # nodule center in voxel space (still x,y,z ordering)\r\n</code></pre>\r\n<p>The center of the nodule is located in the <code>v_center[2]</code> slice of the img_array. We pass the node information to the <code>make_mask()</code> function and copy the generated masks and the image for the <code>v_center[2]</code>slice and the slice above and below it.</p>\r\n<pre><code>i = 0\r\nfor i_z in range(int(v_center[2])-1,int(v_center[2])+2):\r\n    mask = make_mask(center,diam,i_z*spacing[2]+origin[2],width,height,spacing,origin)\r\n    masks[i] = mask\r\n    imgs[i] = matrix2int16(img_array[i_z])\r\n    i+=1\r\nnp.save(output_path+\"images_%d.npy\" % (fcount) ,imgs)\r\nnp.save(output_path+\"masks_%d.npy\" % (fcount) ,masks)\r\n</code></pre>\r\n<p>In the <code>make_mask()</code> function it is worth noting that the mask coordinates have to match the ordering of the array coordinates. The <code>x</code> and <code>y</code> ordering is flipped. See the next to last line in the below code:</p>\r\n<pre><code>    def make_mask(center,diam,z,width,height,spacing,origin):\r\n    ...\r\n    for v_x in v_xrange:\r\n        for v_y in v_yrange:\r\n            p_x = spacing[0]*v_x + origin[0]\r\n            p_y = spacing[1]*v_y + origin[1]\r\n            if np.linalg.norm(center-np.array([p_x,p_y,z]))&lt;=diam:\r\n                mask[int((p_y-origin[1])/spacing[1]),int((p_x-origin[0])/spacing[0])] = 1.0\r\n    return(mask)\r\n</code></pre>\r\n<p>Should we collect more slices from each scan?</p>\r\n<p>Since the nodule locations are defined in terms of spheres, and the nodules are irregularly shaped, slices near the edges of the spheres may contain no nodule tissue. Using such slices would contaminate the training set with false positives. For this segmentation project, there is probably an optimal number of slices through a nodule that one should incorporate. For simplicity, we stick to 3 and only pull the slices centered on the largest nodule.</p>\r\n<p>Check to make sure the nodule masks look as expected:</p>\r\n<pre><code>import matplotlib.pyplot as plt\r\nimgs = np.load(output_path+'images_0.npy')\r\nmasks = np.load(output_path+'masks_0.npy')\r\nfor i in range(len(imgs)):\r\n    print \"image %d\" % i\r\n    fig,ax = plt.subplots(2,2,figsize=[8,8])\r\n    ax[0,0].imshow(imgs[i],cmap='gray')\r\n    ax[0,1].imshow(masks[i],cmap='gray')\r\n    ax[1,0].imshow(imgs[i]*masks[i],cmap='gray')\r\n    plt.show()\r\n    raw_input(\"hit enter to cont : \")\r\n</code></pre>\r\n<p>The image on the top left is the scan slice. The image on the top right is the node mask. The image on the bottom left is the masked slice, highlighting the node.</p>\r\n<p><a href=\"https://camo.githubusercontent.com/b56a25b4fd89f6145825fcd563cbaf4b0f1773e8/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f6578616d706c655f6c756e615f6d61736b2e706e67\" target=\"_blank\"><img src=\"https://camo.githubusercontent.com/b56a25b4fd89f6145825fcd563cbaf4b0f1773e8/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f6578616d706c655f6c756e615f6d61736b2e706e67\" alt=\"Example LUNA Mask\" data-canonical-src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/example_luna_mask.png\" style=\"max-width: 100%;\" /></a></p>\r\n<p>Close up on the nodule :</p>\r\n<p><a href=\"https://camo.githubusercontent.com/e8babeceac103c9b24ab2300d96f88af37a6844f/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f6578616d706c655f6c756e615f6d61736b5f64657461696c2e706e67\" target=\"_blank\"><img src=\"https://camo.githubusercontent.com/e8babeceac103c9b24ab2300d96f88af37a6844f/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f6578616d706c655f6c756e615f6d61736b5f64657461696c2e706e67\" alt=\"Example LUNA Mask detail\" data-canonical-src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/example_luna_mask_detail.png\" style=\"max-width: 100%;\" /></a></p>\r\n<h2>Isolation of the Lung Region of Interest to Narrow Our Nodule Search <a id=\"user-content-isolation-of-the-lung-region-of-interest-to-narrow-our-nodule-search\" class=\"anchor\" href=\"#isolation-of-the-lung-region-of-interest-to-narrow-our-nodule-search\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\r\n<p>The node masks seem to be constructed properly. The next step is to isolate the lungs in the images. We'll need to import some skimage image processing modules for this step. The general strategy is to threshold the image to isolate the regions within the image, and then to identify which of those regions are the lungs. The lungs have a high constrast with the surrounding tissue, so the thresholding is fairly straightforward. We use some ad-hoc criteria for eliminating the non-lung regions from the image which do not apply equally to all data sets.</p>\r\n<p>In addition to our previous imports, we'll make use of ...</p>\r\n<pre><code>from skimage import morphology\r\nfrom skimage import measure\r\nfrom sklearn.cluster import KMeans\r\nfrom skimage.transform import resize\r\n</code></pre>\r\n<p>These steps are found in LUNA_segment_lung_ROI.py</p>\r\n<p>The arrays were loaded as <code>dtype = np.float64</code> because <code>KMeans</code> in sklearn has a bug related to the precision of the input to <code>KMeans</code>.</p>\r\n<p>We'll walk through the steps of isolating the lung ROI with <code>img</code>, which is a 512 X 512 slice from the set we extracted from the LUNA 2016 data, which looks like:</p>\r\n<p><a href=\"https://camo.githubusercontent.com/bf9ec6b8dae66060c1240df73cd2cb78c1b76395/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570312e706e67\" target=\"_blank\"><img src=\"https://camo.githubusercontent.com/bf9ec6b8dae66060c1240df73cd2cb78c1b76395/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570312e706e67\" alt=\"ROI Step 1\" data-canonical-src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/ROI_step1.png\" style=\"max-width: 100%;\" /></a></p>\r\n<h3>Thresholding <a id=\"user-content-thresholding\" class=\"anchor\" href=\"#thresholding\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h3>\r\n<p>Our first step is to standardize the pixel values and take a look at the intensity distribution</p>\r\n<pre><code>img = imgs_to_process[i]\r\n#Standardize the pixel values\r\nmean = np.mean(img)\r\nstd = np.std(img)\r\nimg = img-mean\r\nimg = img/std\r\nplt.hist(img.flatten(),bins=200)\r\n</code></pre>\r\n<p><a href=\"https://camo.githubusercontent.com/0c968db8cbff463032329ba33f10dda192b5b376/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570315f686973742e706e67\" target=\"_blank\"><img src=\"https://camo.githubusercontent.com/0c968db8cbff463032329ba33f10dda192b5b376/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570315f686973742e706e67\" alt=\"ROI Step 1 hist\" data-canonical-src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/ROI_step1_hist.png\" style=\"max-width: 100%;\" /></a></p>\r\n<p>The underflow peak near -1.5 is the black out-of-scanner part of the image. The peaks around 0.0 are the background and lung interior and the wide clumps from 1.0 to 2.0 are the non-lung-tissue and bone. The structure of this histogram varies throughout the data set. Two images are shown below that are typical of the data set. The one on the left has the same black background around a grey circular region of scanner data as is present in <code>img</code>. That black background is not present in the image on the right, making for a very different pixel value histogram.</p>\r\n<p><a href=\"https://camo.githubusercontent.com/c17f3276c944b99f1462f77e264e07a643424a3f/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f686973745f646966662e706e67\" target=\"_blank\"><img src=\"https://camo.githubusercontent.com/c17f3276c944b99f1462f77e264e07a643424a3f/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f686973745f646966662e706e67\" alt=\"ROI Hist Diff\" data-canonical-src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/ROI_hist_diff.png\" style=\"max-width: 100%;\" /></a></p>\r\n<p>We have to make sure that we set our threshold between the lung pixel values and the denser tissue pixel values. To do this, we reset the pixels with the minimum value to the average pixel value near the center of the picture and perform kmeans clustering with k=2. This seems to work well for both scenarios.</p>\r\n<pre><code>middle = img[100:400,100:400] \r\nmean = np.mean(middle)  \r\nmax = np.max(img)\r\nmin = np.min(img)\r\n#move the underflow bins\r\nimg[img==max]=mean\r\nimg[img==min]=mean\r\nkmeans = KMeans(n_clusters=2).fit(np.reshape(middle,[np.prod(middle.shape),1]))\r\ncenters = sorted(kmeans.cluster_centers_.flatten())\r\nthreshold = np.mean(centers)\r\nthresh_img = np.where(img&lt;threshold,1.0,0.0)  # threshold the image\r\n</code></pre>\r\n<p>Which produces a satisfactory separation of regions for both types of images and eliminates the black halo in the one on the left</p>\r\n<p><a href=\"https://camo.githubusercontent.com/4f4d9122302289fa6086784a3ff992d7e4b60322/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570322e706e67\" target=\"_blank\"><img src=\"https://camo.githubusercontent.com/4f4d9122302289fa6086784a3ff992d7e4b60322/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570322e706e67\" alt=\"ROI Step 2\" data-canonical-src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/ROI_step2.png\" style=\"max-width: 100%;\" /></a></p>\r\n<h3>Erosion and Dilation <a id=\"user-content-erosion-and-dilation\" class=\"anchor\" href=\"#erosion-and-dilation\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h3>\r\n<p>We then use an erosion and dilation to fill in the incursions into the lungs region by radio-opaque tissue, followed by a selection of the regions based on the bounding box sizes of each region. The initial set of regions looks like</p>\r\n<pre><code>eroded = morphology.erosion(thresh_img,np.ones([4,4]))\r\ndilation = morphology.dilation(eroded,np.ones([10,10]))\r\nlabels = measure.label(dilation)\r\nlabel_vals = np.unique(labels)\r\nplt.imshow(labels)\r\n</code></pre>\r\n<p><a href=\"https://camo.githubusercontent.com/c3a76edc73cae53927f118bff131f2ed360b312b/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570332e706e67\" target=\"_blank\"><img src=\"https://camo.githubusercontent.com/c3a76edc73cae53927f118bff131f2ed360b312b/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570332e706e67\" alt=\"ROI Step 3\" data-canonical-src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/ROI_step3.png\" style=\"max-width: 100%;\" /></a></p>\r\n<h3>Cutting non-ROI Regions <a id=\"user-content-cutting-non-roi-regions\" class=\"anchor\" href=\"#cutting-non-roi-regions\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h3>\r\n<p>The cuts applied to each region bounding box were determined empirically and seem to work well for the LUNA data, but may not be generally applicable</p>\r\n<pre><code>labels = measure.label(dilation)\r\nlabel_vals = np.unique(labels)\r\nregions = measure.regionprops(labels)\r\ngood_labels = []\r\nfor prop in regions:\r\n    B = prop.bbox\r\n    if B[2]-B[0]&lt;475 and B[3]-B[1]&lt;475 and B[0]&gt;40 and B[2]&lt;472:\r\n        good_labels.append(prop.label)\r\nmask = np.ndarray([512,512],dtype=np.int8)\r\nmask[:] = 0\r\n#\r\n#  The mask here is the mask for the lungs--not the nodes\r\n#  After just the lungs are left, we do another large dilation\r\n#  in order to fill in and out the lung mask \r\n#\r\nfor N in good_labels:\r\n    mask = mask + np.where(labels==N,1,0)\r\nmask = morphology.dilation(mask,np.ones([10,10])) # one last dilation\r\nplt.imshow(mask,cmap='gray')\r\n</code></pre>\r\n<p><a href=\"https://camo.githubusercontent.com/fce217e585b6397d9a1a5a5ef592cbe66eef0beb/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570342e706e67\" target=\"_blank\"><img src=\"https://camo.githubusercontent.com/fce217e585b6397d9a1a5a5ef592cbe66eef0beb/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570342e706e67\" alt=\"ROI Step 4\" data-canonical-src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/ROI_step4.png\" style=\"max-width: 100%;\" /></a></p>\r\n<h3>Applying the ROI Masks <a id=\"user-content-applying-the-roi-masks\" class=\"anchor\" href=\"#applying-the-roi-masks\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h3>\r\n<p>The next step in LUNA_segment_lung_ROI.py is applying the mask of the lung ROI to each of the images, cropping down to the bounding square of the lungs ROI, and then resizing the resulting image to 512 X 512.</p>\r\n<pre><code>masks = np.load(working_path+\"lungmask_0.py\")\r\nimgs = np.load(working_path+\"images_0.py\")\r\nimgs = masks*imgs\r\n</code></pre>\r\n<p>...crop to bounding square and resize to 512 X 512...</p>\r\n<p>Then we perform some final pixel normalization. This is because the mask sends the non ROI area in the picture to 0, and that operation is not sensitive to the pixel value distribution. To fix this, we get the mean and standard deviation of the masked region and send the background (now zero) to the lower end of the pixel distribution (<code>-1.2*stdev</code>, which was chosen empirically).</p>\r\n<pre><code>#\r\n# renormalizing the masked image (in the mask region)\r\n#\r\nnew_mean = np.mean(img[mask&gt;0])  \r\nnew_std = np.std(img[mask&gt;0])\r\n#\r\n#  Pushing the background color up to the lower end\r\n#  of the pixel range for the lungs\r\n#\r\nold_min = np.min(img)       # background color\r\nimg[img==old_min] = new_mean-1.2*new_std   # resetting backgound color\r\nimg = img-new_mean\r\nimg = img/new_std\r\n</code></pre>\r\n<p>The final product is a set of lungs that is ready to be compiled into our training example set.</p>\r\n<p><a href=\"https://camo.githubusercontent.com/7c57f917ddb31c8f1b4522b6a8b1b05d041cc45e/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570352e706e67\" target=\"_blank\"><img src=\"https://camo.githubusercontent.com/7c57f917ddb31c8f1b4522b6a8b1b05d041cc45e/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f524f495f73746570352e706e67\" alt=\"ROI Step 5\" data-canonical-src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/ROI_step5.png\" style=\"max-width: 100%;\" /></a></p>\r\n<p>These images and the correspondingly trimmed and rescaled masks are randomized and sent to a single file that contains a numpy array of dimension <code>[&lt;num_images&gt;,1,512,512]</code>. The 1 is important as the U-net is enabled for multiple channels.</p>\r\n<pre><code>#\r\n#  Writing out images and masks as 1 channel arrays for input into network\r\n#\r\nfinal_images = np.ndarray([num_images,1,512,512],dtype=np.float32)\r\nfinal_masks = np.ndarray([num_images,1,512,512],dtype=np.float32)\r\nfor i in range(num_images):\r\n    final_images[i,0] = out_images[i]\r\n    final_masks[i,0] = out_nodemasks[i]\r\nrand_i = np.random.choice(range(num_images),size=num_images,replace=False)\r\ntest_i = int(0.2*num_images)\r\nnp.save(working_path+\"trainImages.npy\",final_images[rand_i[test_i:]])\r\nnp.save(working_path+\"trainMasks.npy\",final_masks[rand_i[test_i:]])\r\nnp.save(working_path+\"testImages.npy\",final_images[rand_i[:test_i]])\r\nnp.save(working_path+\"testMasks.npy\",final_masks[rand_i[:test_i]])\r\n</code></pre>\r\n<p>You can check the ROI isolationg by examining the lung masks and the original files:</p>\r\n<pre><code>imgs = np.load(working path+'images_0.npy')\r\nlungmask = np.load(working_path+'lungmask_0.npy')\r\nfor i in range(len(imgs)):\r\n    print \"image %d\" % i\r\n    fig,ax = plt.subplots(2,2,figsize=[8,8])\r\n    ax[0,0].imshow(imgs[i],cmap='gray')\r\n    ax[0,1].imshow(lungmask[i],cmap='gray')\r\n    ax[1,0].imshow(imgs[i]*lungmask[i],cmap='gray')\r\n    plt.show()\r\n    raw_input(\"hit enter to cont : \")\r\n</code></pre>\r\n<h3>Dice Ceofficient Cost function for Segmentation <a id=\"user-content-dice-ceofficient-cost-function-for-segmentation\" class=\"anchor\" href=\"#dice-ceofficient-cost-function-for-segmentation\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h3>\r\n<p>The network we'll be using is the U-net linked to the beginning of the tutorial which uses the keras framework. The loss function is the dice coefficient <a href=\"https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient\">https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient</a> comparing the predicted and actual node mask.</p>\r\n<p>The following code snippets are all taken from LUNA_train_unet.py</p>\r\n<p>The loss function is as follows:</p>\r\n<pre><code>smooth = 1.\r\n# Tensorflow version for the model\r\ndef dice_coef(y_true, y_pred):\r\n    y_true_f = K.flatten(y_true)\r\n    y_pred_f = K.flatten(y_pred)\r\n    intersection = K.sum(y_true_f * y_pred_f)\r\n    return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)\r\ndef dice_coef_loss(y_true, y_pred):\r\n    return -dice_coef(y_true, y_pred)\r\n</code></pre>\r\n<p>Which is similar to the metric used to evaluate the Ultrasound Nerve Segmentation challenge that this network was originally written for (once again, see the link at the beginning of this tutorial).</p>\r\n<h3>Loading the Segmenter <a id=\"user-content-loading-the-segmenter\" class=\"anchor\" href=\"#loading-the-segmenter\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h3>\r\n<p>The function call</p>\r\n<pre><code>model = get_unet() \r\nmodel_checkpoint = ModelCheckpoint('unet.hdf5', monitor='loss', save_best_only=True)\r\n</code></pre>\r\n<p>will compile and return the model and tell keras to save the model weights during checkpoints. If you want to load the best weights from a previous training session or use the weights included in this tutorial's repo, load the weight file with the line</p>\r\n<pre><code>model.load_weights('unet.hdf5')\r\n</code></pre>\r\n<h3>Training the Segmenter <a id=\"user-content-training-the-segmenter\" class=\"anchor\" href=\"#training-the-segmenter\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h3>\r\n<p>Calling LUNA_train_unet.py from the command line will automatically attempt to load a unet.hdf5 file from the current directory, train it according to the parameters set by the line</p>\r\n<pre><code>model.fit(imgs_train, imgs_mask_train, batch_size=2, nb_epoch=20, \r\n           verbose=1, shuffle=True,callbacks=[model_checkpoint])\r\n</code></pre>\r\n<p>in the script, and make predictions on the test set.</p>\r\n<pre><code>num_test = len(imgs_test)\r\nimgs_mask_test = np.ndarray([num_test,1,512,512],dtype=np.float32)\r\nfor i in range(num_test):\r\n    imgs_mask_test[i] = model.predict([imgs_test[i:i+1]], verbose=0)[0]\r\nnp.save('masksTestPredicted.npy', imgs_mask_test)\r\nmean = 0.0\r\nfor i in range(num_test):\r\n    mean+=dice_coef_np(imgs_mask_test_true[i,0], imgs_mask_test[i,0])\r\nmean/=num_test\r\nprint(\"Mean Dice Coeff : \",mean)\r\n</code></pre>\r\n<p>The <code>model.predict()</code> function can take more than one case at a time, but that can quickly overload a GPU, so we are looping over individual cases.</p>\r\n<p>The final results for this tutorial were produced using a multi-GPU machine using TitanX's. For a home GPU computation benchmark, a personal set up with a GTX970 we were able to run 20 epochs with a training set size of 320 and batch size of 2 in about an hour. We started obtaing reasonable nodule mask predictions after about 3 hours of training once the reported loss value approached 0.3.</p>\r\n<p>An example segmentation is given here for the three slices taken from a patient scan. The perfect circle is the \"true\" node mask from the LUNA annotationc.csv file, and the red is the predicted node region from the segmenter. The original image is given in the top right.</p>\r\n<p><a href=\"https://camo.githubusercontent.com/827bf52a6a66c475d1c4ecb1b7869cb689d22063/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f6578616d706c655f7365676d656e746174696f6e2e706e67\" target=\"_blank\"><img src=\"https://camo.githubusercontent.com/827bf52a6a66c475d1c4ecb1b7869cb689d22063/68747470733a2f2f6b6167676c65322e626c6f622e636f72652e77696e646f77732e6e65742f636f6d7065746974696f6e732f6b6167676c652f363030342f6d656469612f6578616d706c655f7365676d656e746174696f6e2e706e67\" alt=\"Example Segmentation\" data-canonical-src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/6004/media/example_segmentation.png\" style=\"max-width: 100%;\" /></a></p>\r\n<h2>Training a Classifier for Identifying Cancer <a id=\"user-content-training-a-classifier-for-identifying-cancer\" class=\"anchor\" href=\"#training-a-classifier-for-identifying-cancer\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\r\n<p>Now we are ready to begin training a classifier using our image segmentation from the previous sections to generate features.</p>\r\n<p>The Data Science Bowl training data set must be fed through the segmenter, which can be done largely by reusing the code used to treat the LUNA data. There are two points where this deviates.</p>\r\n<p>First of all, the DSB data is in dicom format, which can be read using the pydicom module</p>\r\n<pre><code>import dicom\r\ndc = dicom.read_file(filename)\r\nimg = dc.pixel_array\r\n</code></pre>\r\n<p>Secondly, in order to locate nodes in the scans, every layer of the scan must be run through the segmenter, and thus every layer must also be subject to the image processing to mask off the ROI. This can be a very time consuming process.</p>\r\n<h2>Simple classifier based on nodule features <a id=\"user-content-simple-classifier-based-on-nodule-features\" class=\"anchor\" href=\"#simple-classifier-based-on-nodule-features\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\r\n<p>We start by characterizing some of the features of the nodule maps and putting them into a feature vector that we can use for classification purposes. Our list of features is by no means exhaustive and is meant to illustrate the process of developing some meterics that could be used to characterize the segmented regions where nodules are likely.</p>\r\n<p>We encourage you to play with adding some new features, explore convolutional models for extracting features from the region of interest directly. We have included some features about the average size, morphology, and position within the image for use in model building.</p>\r\n<pre><code>def getRegionMetricRow(fname = \"nodules.npy\"):\r\n    seg = np.load(fname)\r\n    nslices = seg.shape[0]\r\n    #metrics\r\n    totalArea = 0.\r\n    avgArea = 0.\r\n    maxArea = 0.\r\n    avgEcc = 0.\r\n    avgEquivlentDiameter = 0.\r\n    stdEquivlentDiameter = 0.\r\n    weightedX = 0.\r\n    weightedY = 0.\r\n    numNodes = 0.\r\n    numNodesperSlice = 0.\r\n    # do not allow any nodes to be larger than 10% of the pixels to eliminate background regions\r\n    maxAllowedArea = 0.10 * 512 * 512 \r\n    areas = []\r\n    eqDiameters = []\r\n    for slicen in range(nslices):\r\n        regions = getRegionFromMap(seg[slicen,0,:,:])\r\n        for region in regions:\r\n            if region.area &gt; maxAllowedArea:\r\n                continue\r\n            totalArea += region.area\r\n            areas.append(region.area)\r\n            avgEcc += region.eccentricity\r\n            avgEquivlentDiameter += region.equivalent_diameter\r\n            eqDiameters.append(region.equivalent_diameter)\r\n            weightedX += region.centroid[0]*region.area\r\n            weightedY += region.centroid[1]*region.area\r\n            numNodes += 1\r\n    weightedX = weightedX / totalArea \r\n    weightedY = weightedY / totalArea\r\n    avgArea = totalArea / numNodes\r\n    avgEcc = avgEcc / numNodes\r\n    avgEquivlentDiameter = avgEquivlentDiameter / numNodes\r\n    stdEquivlentDiameter = np.std(eqDiameters)\r\n    maxArea = max(areas)\r\n    numNodesperSlice = numNodes*1. / nslices\r\n    return np.array([avgArea,maxArea,avgEcc,avgEquivlentDiameter,\\\r\n                     stdEquivlentDiameter, weightedX, weightedY, numNodes, numNodesperSlice])\r\n</code></pre>\r\n<pre><code>def getRegionFromMap(slice_npy):\r\n    thr = np.where(slice_npy &gt; np.mean(slice_npy),0.,1.0)\r\n    label_image = label(thr)\r\n    labels = label_image.astype(int)\r\n    regions = regionprops(labels)\r\n    return regions\r\n</code></pre>\r\n<pre><code>import pickle\r\ndef createFeatureDataset(nodfiles=None):\r\n    if nodfiles == None:\r\n        noddir = \"nodulesdir/\"\r\n        nodfiles = glob(noddir +\"*npy\")\r\n    # dict with mapping between truth and \r\n    truthdata = pickle.load(open(\"truthdict.pkl\",'r'))\r\n    numfeatures = 9\r\n    feature_array = np.zeros((len(nodfiles),numfeatures))\r\n    truth_metric = np.zeros((len(nodfiles)))\r\n    for i,nodfile in enumerate(nodfiles):\r\n        patID = nodfile.split(\"_\")[2]\r\n        truth_metric[i] = truthdata[int(patID)]\r\n        feature_array[i] = getRegionMetricRow(nodfile)\r\n    np.save(\"dataY.npy\", truth_metric)\r\n    np.save(\"dataX.npy\", feature_array)\r\n</code></pre>\r\n<p>Once we've created our feature dataset, we can create a simple classifer based on the featureset to determine the cancer diagnosis. We've chose to illustrate two popular classifiers Random Forest and XGBoost, because they are both robust to overfitting and quick to train. The common python implementation of XGBoost also allows for easy modification of the objective function and reweighting the class importance, so that we can reweight the optimization problem to give more weight to cancer cases.</p>\r\n<pre><code>from sklearn import cross_validation\r\nfrom sklearn.cross_validation import StratifiedKFold as KFold\r\nfrom sklearn.metrics import classification_report\r\nfrom sklearn.ensemble import RandomForestClassifier as RF\r\nimport xgboost as xgb\r\nX = np.load(\"dataX.npy\")\r\nY = np.load(\"dataY.npy\")\r\n#Random Forest\r\nkf = KFold(Y, n_folds=3)\r\ny_pred = Y * 0\r\ny_pred_prob = Y * 0\r\nfor train, test in kf:\r\n    X_train, X_test, y_train, y_test = X[train,:], X[test,:], Y[train], Y[test]\r\n    clf = RF(n_estimators=100, n_jobs=3)\r\n    clf.fit(X_train, y_train)\r\n    y_pred[test] = clf.predict(X_test)\r\n    y_pred_prob[test] = clf.predict_proba(X_test)[:,1]\r\nprint ('Random Forest')\r\nprint classification_report(Y, y_pred, target_names=[\"No Cancer\", \"Cancer\"])\r\nprint(\"logloss\",logloss(Y, y_pred_prob))\r\n#XGBoost\r\nprint (\"XGBoost\")\r\nkf = KFold(Y, n_folds=3)\r\ny_pred = Y * 0\r\ny_pred_prob = Y * 0\r\nfor train, test in kf:\r\n    X_train, X_test, y_train, y_test = X[train,:], X[test,:], Y[train], Y[test]\r\n    clf = xgb.XGBClassifier(objective=\"binary:logistic\", scale_pos_weight=3 )\r\n    clf.fit(X_train, y_train)\r\n    y_pred[test] = clf.predict(X_test)\r\n    y_pred_prob[test] = clf.predict_proba(X_test)[:,1]\r\nprint classification_report(Y, y_pred, target_names=[\"No Cancer\", \"Cancer\"])\r\nprint(\"logloss\",logloss(Y, y_pred_prob))\r\n# All Cancer\r\nprint \"Predicting all positive\"\r\ny_pred = np.ones(Y.shape)\r\nprint classification_report(Y, y_pred, target_names=[\"No Cancer\", \"Cancer\"])\r\nprint(\"logloss\",logloss(Y, y_pred))\r\n# No Cancer\r\nprint \"Predicting all negative\"\r\ny_pred = Y*0\r\nprint classification_report(Y, y_pred, target_names=[\"No Cancer\", \"Cancer\"])\r\nprint(\"logloss\",logloss(Y, y_pred))\r\n</code></pre>\r\n<p>We compare the results for Random forest, XGBoost, and two models consisting of only predicting cancer and only predicting no cancer.</p>\r\n<pre><code>Random Forest\r\n             precision    recall  f1-score   support\r\n  No Cancer       0.81      0.98      0.89       463\r\n     Cancer       0.17      0.02      0.03       107\r\navg / total       0.69      0.80      0.73       570\r\n('logloss', 0.52600332670816652)\r\nXGBoost\r\n             precision    recall  f1-score   support\r\n  No Cancer       0.83      0.86      0.84       463\r\n     Cancer       0.27      0.21      0.24       107\r\navg / total       0.72      0.74      0.73       570\r\n('logloss', 0.5700685138621493)\r\nPredicting all positive\r\n             precision    recall  f1-score   support\r\n  No Cancer       0.00      0.00      0.00       463\r\n     Cancer       0.19      1.00      0.32       107\r\navg / total       0.04      0.19      0.06       570\r\n('logloss', 28.055831025357818)\r\nPredicting all negative\r\n             precision    recall  f1-score   support\r\n  No Cancer       0.81      1.00      0.90       463\r\n     Cancer       0.00      0.00      0.00       107\r\navg / total       0.66      0.81      0.73       570\r\n('logloss', 6.4835948671148085)\r\n</code></pre>\r\n<h2>Where to go next? <a id=\"user-content-where-to-go-next\" class=\"anchor\" href=\"#where-to-go-next\" aria-hidden=\"true\"><svg aria-hidden=\"true\" class=\"octicon octicon-link\" height=\"16\" version=\"1.1\" viewbox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\r\n<p>We've given you a framework for approaching this problem that combines a deep learning based segmentation approach with an older computer vision approach of hand designed features. From here you have lots of ways to improve the u-net model with more data, or additional preprocessing. The classification piece could be replaced by a another convolutional nueral net or you could take more advantage of the 3d nature of the nodules that we've mostly considered as independant 2d slices here.</p>\r\n</div>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "Resources",
      "content": "<p><span style=\"color: #555555;\" color=\"rgb(85,85,85)\"><a href=\"http://www.DataScienceBowl.com\">DataScienceBowl.com</a></span></p>\r\n<p><span style=\"color: #555555;\" color=\"rgb(85,85,85)\">AWS research and technical computing website: <a href=\"http://www.aws.amazon.com/rtc\">www.aws.amazon.com/rtc</a></span></p>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "Engagement Contest",
      "content": "<h2 id=\"rules-and-guidelines\">Rules and Guidelines</h2>\n\n<p>The Data Science Bowl Engagement contest is open to all individuals over the age of 18 at the time of entry and to all validly formed legal entities that have not declared or been declared in bankruptcy. The contest will contain three phases, each with a separate mini challenge and instructions on how to participate. The instructions on how to participate in the first mini-challenge/phase are listed below.</p>\n\n\n\n<h3 id=\"overall-ccontest-overview\">OVERALL CONTEST OVERVIEW:</h3>\n\n<p><strong>Mini-Challenge # 1</strong>: <em>February 1 – 15 3:00 p.m. ET; Prize: $2,500</em></p>\n\n<p><strong>Mini-Challenge #2</strong>: <em>February 15 – 28 3:00 p.m. ET; Prize: $2,500</em></p>\n\n<p><strong>Mini-Challenge #3</strong>: <em>March 1 – 15  3:00 p.m. ET; Prize: $5,000</em></p>\n\n<h3 id=\"mini-challenge-1-feb-1-15-how-to-participate-phase-1\">Mini-Challenge #1 (Feb 1-15): HOW TO PARTICIPATE (PHASE 1):</h3>\n\n<ul>\n<li>Using <strong>Instagram and/or Twitter</strong>, share a post using the <strong>hashtags #DataSciBowl AND #Data4Good</strong>. Start sharing NOW until February 15th for a chance to win $2,500!</li>\n<li>We want you to help spread the Data Science Bowl by sharing your connection and excitement about it! Why are you looking forward to this year’s #DataSciBowl? Do you have a connection to lung cancer, cancer, data science for good, or the Data Science Bowl in general? Show us how you’re excited about the power of data for good! </li>\n<li><strong>Sample Posts:</strong> <br>\n<ul><li><em>Knowledge is power. #Data4Good can help identify lung cancer. #DataSciBowl</em></li>\n<li><em>#DataSciBowl I’m competing for my cousin #Data4Good can help with early detection.</em></li>\n<li><em>The power of data is inspiring. Excited to see the results from the #DataSciBowl &amp; how we can use #Data4Good to fight lung cancer!</em> </li></ul></li>\n</ul>\n\n<h3 id=\"mini-challenge-2-feb-16-28-how-to-participate\">Mini-Challenge #2 (Feb 16-28): HOW TO PARTICIPATE</h3>\n\n<p>Using <strong>Instagram and/or Twitter</strong>, share a post using the <strong>hashtags #DataSciBowl AND #Data4Good</strong>. Start sharing NOW until February 28th to qualify to win $2,500!</p>\n\n<p>We want you to share your commitment to the Data Science Bowl (participating, watching, promoting, other something else) by writing a pledge to #Data4Good. What will #DataSciBowl mean to you? You might choose to pledge your passion, your best guess, your undivided attention. Or the challenge might inspire you to pledge a donation or volunteer with a nonprofit. Show us how the power of data for good inspires you.</p>\n\n<p><strong>Sample Posts:</strong></p>\n<ul>\n<li><em>My pledge for #DataSciBowl will help my brother fight his cancer. #Data4Good</em></li>\n<li><em> I’m competing in #DataSciBowl with coworkers My pledge is to be a top-10 team. #Data4Good</em></li>\n<li><em>Did you see the results at #DataSciBowl? My pledge: This is the end lung cancer! #Data4Good</em> </li>\n<li><em>I dedicate my #DataSciBowl participation to Sarah who lost her life too early to cancer #Data4Good</em> </li>\n<li><em>#Data4Good I pledge to use data to fight disease by participating in the #DataSciBowl.</em> </li>\n</ul>\n\n\n<h3 id=\"mini-challenge-3-march-1-15-how-to-participate\">Mini-Challenge #3 (March 1-15): HOW TO PARTICIPATE</h3>\n\n<ul>\n<li>Using <strong>Instagram and/or Twitter</strong>, share a behind-the-scene moment in photo or video format from your experience with the Data Science Bowl using the <strong>hashtags #DataSciBowl and #Data4Good</strong>. Start sharing NOW until March 15 to qualify to win $5,000!</li>\n<li>Data science for social good is an incredibly powerful initiative – tell the world what inspired you to enter the Data Science Bowl. Other great ideas for posts include a photo or video of your team working, having fun, celebrating a success, or how you first learned about the competition. From your team’s special way of brainstorming new ideas, to your favorite food or beverage while working – we want to hear what’s going on “inside the Data Science Bowl.”</li>\n</ul>\n\n<h3 id=\"contest-criteria\">CONTEST CRITERIA:</h3>\n\n<ul>\n<li>Each mini-challenge will have one winner. One winner will be chosen for during each phase of the contest. The winner for each of each mini-challenge will be randomly selected via a random drawing on the last day of each mini-challenge: <strong>February 15 (#1)</strong>, <strong>February 28 (#2)</strong>, <strong>March 15 (#3), 2017</strong>. Entries will be closed at 3pm ET on the last day of each mini-challenge/phase of the contest.</li>\n<li>In order to be eligible for the random drawing, you must use the designated hashtag(s) for each of the respective mini-challenges in which you are participating. (e.g., phase mini-challenge #1 = #DataSciBowl &amp; #Data4Good) </li>\n<li>To be eligible, entries must use appropriate content – no foul language or trolling, and use only releasable, allowable, and appropriate imagery.</li>\n<li>Individuals are encouraged to share their personal connections to the Data Science Bowl competition, lung cancer, data science for social good, or other related topics.</li>\n<li>We will announce the winner for each phase in a Tweet from @kaggle, and t then contact each winner offline for prize award details.</li>\n<li>We encourage you to participate in each of the 3 phases throughout the contest – since the winner selection for each is a random drawing, an individual has the potential to win more than one contest! </li>\n</ul>\n\n<p>ELIGIBILITY NOTE: Members of the following organizations are invited to participate in the competition, however, they will not be eligible to win a cash prize: Booz Allen Hamilton, Amazon Web Services, NVIDIA, NCI Division of Cancer Treatment and Diagnosis, NCI Division of Cancer Prevention, Functional Image Analysis group, Radboud University, The Cancer Imaging Archive, Lahey Hospital &amp; Medical Center, and Copenhagen University Hospital. Additionally, anyone who has previously accessed any of the data sources outside the purview of this competition will not be eligible to win a cash prize. Officers, directors, employees and advisory board members (and their immediate families and members of the same household) of the Competition Sponsor, Kaggle and their respective affiliates, subsidiaries, contractors (with the express exception of Kaggle’s authorized Kaggle Community Evangelists), agents, judges and advertising and promotion agencies are not eligible for prizes. Residents of a country designated by the United States Treasury’s Office of Foreign Assets Control (see <a href=\"http://www.treasury.gov/resource-center/sanctions/SDN-List/Pages/default.aspx\">http://www.treasury.gov/resource-center/sanctions/SDN-List/Pages/default.aspx</a> for additional information) are not eligible to receive prizes.</p>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    }
  ]
}